📄 qqclient.java
字号:
*/
public String getLoginServer() {
return loginServer;
}
/**
* @return Returns the user.
*/
public QQUser getUser() {
return user;
}
/**
* 在登陆之后,为sender和packet processor加上QQListener
*/
private void initQQListeners() {
port.removeAllQQListener();
pp.removeAllQQListener();
int size = qqListeners.size();
for(int i = 0; i < size; i++) {
port.addQQListener((QQListener)qqListeners.get(i));
pp.addQQListener((QQListener)qqListeners.get(i));
}
port.addQQListener(this);
pp.addQQListener(this);
}
/**
* 登陆
*/
/*
public void login() {
if (user != null && !logging) {
// 设置状态为正在登陆
logging = true;
// 如果登陆服务器未设置,随机在列表中选择一个
if(loginServer == null) {
if(user.isUdp())
loginServer = QQ.udpServers[new Random().nextInt(QQ.udpServerAmount)];
else
loginServer = QQ.tcpServers[new Random().nextInt(QQ.tcpServerAmout)];
}
// 登陆
login(loginServer, QQ.QQ_UDP_PORT);
}
}*/
/**
* 登陆
* @throws Exception
*/
public void login() throws Exception {
if (user != null && !logging && loginServer != null) {
// 登陆
login(loginServer, user.isUdp()?QQ.QQ_UDP_PORT:QQ.QQ_TCP_PORT);
}
}
/**
* @param loginServer 登陆服务器
* @param loginPort 登陆端口
* @throws Exception
*/
protected void login(String loginServer, int loginPort) throws Exception {
// 检查是否设置了用户名和密码
if (user != null) {
// 停止以前的线程,如果有的话
logout();
// 设置状态为正在登陆
logging = true;
// 检查是什么登陆模式,udp还是tcp
try {
if (user.isUdp()) {
log.debug("使用UDP服务器: " + loginServer);
// 创建端口类
if(proxyType == QQ.PROXY_SOCKS5) {
log.debug("使用Socks 5代理 " + proxyAddress);
port = new UDPSocks5Port(proxyAddress, new InetSocketAddress(loginServer, loginPort), proxyUsername, proxyPassword);
} else
port = new UDPPort(new InetSocketAddress(loginServer, loginPort));
} else {
log.debug("使用TCP服务器: " + loginServer);
// 创建发送类和接收类
if(proxyType == QQ.PROXY_SOCKS5) {
log.debug("使用Socks 5代理 " + proxyAddress);
port = new TCPSocks5Port(proxyAddress, new InetSocketAddress(loginServer, loginPort), proxyUsername, proxyPassword);
} else if(proxyType == QQ.PROXY_HTTP) {
log.debug("使用HTTP代理 " + proxyAddress);
port = new TCPHttpPort(proxyAddress, new InetSocketAddress(loginServer, QQ.QQ_HTTP_PORT), proxyUsername, proxyPassword);
} else
port = new TCPPort(new InetSocketAddress(loginServer, loginPort));
}
// 添加包事件监听器
port.addPacketListener(pp);
// 初始化QQ事件监听器
initQQListeners();
// 构造登陆请求包
LoginPacket packet = new LoginPacket();
log.debug("登陆请求包已构造,序号为: " + (int)packet.getSequence());
// 启动port
port.start();
// 发送请求包
port.add(packet);
} catch (UnknownHostException e) {
throw new Exception("服务器名称无法解析");
} catch (SocketException e) {
throw new Exception("无法连接上服务器");
} catch (IOException e) {
throw new Exception("无法连接上服务器");
} catch (UnresolvedAddressException e) {
throw new Exception("无法解析服务器地址");
} catch (Exception e) {
throw new Exception("未知错误");
}
}
}
/**
* 退出QQ会话
*/
public void logout() {
// 情况包监视器缓冲
monitor.clear();
// 设置用户状态
if(!loginRedirect && (logging || user.isLoggedIn()))
user.setStatus(QQ.QQ_FRIEND_STATUS_OFFLINE);
user.setLoggedIn(false);
// 设置正在登录标志为false
logging = false;
loginRedirect = false;
if(port != null) {
// 情况发送队列
port.clear();
// 发送logout包
LogoutPacket packet = new LogoutPacket();
port.send(packet);
}
// 执行清理工作
clean(kaThread, port);
port = null;
kaThread = null;
}
// 处理得到好友列表结束事件
private void processGetFriendListEnd(QQEvent e) {
// 好友已经全部得到了,那么接着发送请求在线好友列表的包
log.debug("好友全部得到,开始请求在线好友名单");
getFriendOnline();
}
// 处理得到好友列表成功事件
private void processGetFriendListSuccess(QQEvent e) {
// 得到包
GetFriendListReplyPacket packet = (GetFriendListReplyPacket)e.getSource();
// 如果包的position属性不等于QQ_FRIENDS_LIST_POSITION_END,表明还有好友没有得到,继续请求
log.debug("还有好友没有列出,继续请求好友");
GetFriendListPacket gflPacket = new GetFriendListPacket();
gflPacket.setStartPosition(packet.position);
sendPacket(gflPacket);
}
// 处理得到在线好友列表成功事件
private void processGetFriendOnlineSuccess(QQEvent e) {
// 得到包
GetFriendOnlineReplyPacket packet = (GetFriendOnlineReplyPacket)e.getSource();
// 如果position不等于QQ_FRIEND_ONLINE_LIST_POSITION_END,说明还有信息没有得到
log.debug("还有在线好友没有列出,继续请求在线好友列表");
GetFriendOnlinePacket gfoPacket = new GetFriendOnlinePacket();
gfoPacket.setStartPosition(packet.position);
sendPacket(gfoPacket);
}
// 处理得到用户信息成功事件
private void processGetUserInfoSuccess(QQEvent e) {
// 得到包
GetUserInfoReplyPacket packet = (GetUserInfoReplyPacket)e.getSource();
// 如果这个user就是我,那就设置我的信息
if(Utils.getInt(packet.contactInfo.infos[packet.contactInfo.qqStr], 0) == user.getQQ())
user.setContactInfo(packet.contactInfo);
}
// 处理Keep Alive成功信息,对Keep Alive Success,QQClient不作什么
// 进一步的分析,只是顺便刷新一下好友状态
private void processKeepAliveSuccess(QQEvent e) {
GetFriendOnlinePacket packet = new GetFriendOnlinePacket();
sendPacket(packet);
}
// 处理登陆成功事件
private void processLoginSuccess() {
if(!user.isLoggedIn()) {
user.setLoggedIn(true);
this.logging = false;
// 启动Keep Alive线程
kaThread = new KeepAliveThread(this);
kaThread.start();
log.debug("Keep Alive线程已经启动");
// 请求密钥
requestKey(QQ.QQ_REQUEST_UNKNOWN_KEY);
requestKey(QQ.QQ_REQUEST_FILE_AGENT_KEY);
// 得到我的信息
GetUserInfoPacket guiPacket = new GetUserInfoPacket();
sendPacket(guiPacket);
// 手动更改我的在线状态,虽然服务器可能也会给我发送这样的信息
ChangeStatusPacket csPacket = new ChangeStatusPacket();
sendPacket(csPacket);
// 如果设置了自动得到好友信息,就请求
if(autoGetFriend)
getFriendList();
}
}
// 处理普通消息事件,只是发一个确认而已
private void processReceiveIM(QQEvent e) {
// 得到包
ReceiveIMPacket packet = (ReceiveIMPacket)e.getSource();
// 生成确认包
ReceiveIMReplyPacket reply = new ReceiveIMReplyPacket(packet.reply);
reply.setSequence(packet.getSequence());
if(port != null)
port.add(reply);
}
// 检查系统消息是否是被踢出,其他消息不关心
private void processKickedOutBySystem(QQEvent e) {
// 得到包
ReceiveIMPacket packet = (ReceiveIMPacket)e.getSource();
// 生成确认包
ReceiveIMReplyPacket reply = new ReceiveIMReplyPacket(packet.reply);
reply.setSequence(packet.getSequence());
if(port != null)
port.add(reply);
// 判断类型
if(packet.systemMessageType == QQ.QQ_RECV_IM_KICK_OUT) {
log.debug("被系统踢出,可能是同一QQ号码在别处登陆");
user.setLoggedIn(false);
logout();
}
}
/* (non-Javadoc)
* @see edu.tsinghua.lumaqq.QQListener#qqEvent(edu.tsinghua.lumaqq.QQEvent)
*/
public void qqEvent(QQEvent e) {
switch(e.type) {
case QQEvent.QQ_LOGIN_SUCCESS:
processLoginSuccess();
break;
case QQEvent.QQ_GET_FRIEND_LIST_SUCCESS:
processGetFriendListSuccess(e);
break;
case QQEvent.QQ_GET_FRIEND_LIST_END:
processGetFriendListEnd(e);
break;
case QQEvent.QQ_GET_FRIEND_ONLINE_SUCCESS:
processGetFriendOnlineSuccess(e);
break;
case QQEvent.QQ_GET_USER_INFO_SUCCESS:
processGetUserInfoSuccess(e);
break;
case QQEvent.QQ_KEEP_ALIVE_SUCCESS:
processKeepAliveSuccess(e);
break;
case QQEvent.QQ_KICKED_OUT_BY_SYSTEM:
processKickedOutBySystem(e);
break;
case QQEvent.QQ_RECEIVE_NORMAL_IM:
case QQEvent.QQ_REQUEST_SEND_FILE:
case QQEvent.QQ_ACCEPT_SEND_FILE:
case QQEvent.QQ_REJECT_SEND_FILE:
case QQEvent.QQ_CANCEL_SEND_FILE:
case QQEvent.QQ_NOTIFY_FILE_TRANSFER_ARGS:
case QQEvent.QQ_REQUEST_ME_CONNECT:
case QQEvent.QQ_UNKNOWN_TYPE_IM:
case QQEvent.QQ_RECEIVE_CLUSTER_IM:
case QQEvent.QQ_REQUEST_JOIN_CLUSTER:
case QQEvent.QQ_REQUEST_JOIN_CLUSTER_APPROVED:
case QQEvent.QQ_REQUEST_JOIN_CLUSTER_REJECTED:
case QQEvent.QQ_I_AM_ADDED_TO_CLUSTER:
case QQEvent.QQ_I_AM_REMOVED_FROM_CLUSTER:
processReceiveIM(e);
break;
case QQEvent.QQ_OPERATION_TIMEOUT:
if(e.operation == QQ.QQ_CMD_LOGIN)
processLoginTimeout();
break;
case QQEvent.QQ_CONNECTION_LOST:
processConnectionLost();
break;
}
}
// 处理连接丢失事件
private void processConnectionLost() {
user.setLoggedIn(false);
logout();
}
// 处理登陆超时事件
private void processLoginTimeout() {
logging = false;
logout();
}
/**
* 移去一个QQ事件监听器
* @param listener QQListener
*/
public void removeQQListener(QQListener listener) {
qqListeners.remove(listener);
if(port != null)
port.removeQQListener(listener);
if(pp != null)
pp.removeQQListener(listener);
}
/**
* 发送一个消息,用给定的字体
* @param message 消息
* @param receiver 接受者QQ号
* @param fontName 字体
*/
public void sendMessage(String message, int receiver, String fontName) {
this.sendMessage(message, receiver, fontName, QQ.QQ_IM_NORMAL_REPLY);
}
/**
* 发送一条消息,可以指定回复类型
* @param message 消息
* @param receiver 接收者QQ号
* @param fontName 字体名
* @param replyType 回复方式,正常回复还是自动回复
*/
public void sendMessage(String message, int receiver, String fontName, byte replyType) {
this.sendMessage(message, receiver, fontName, 9, false, false, false, 0, 0, 0, replyType);
}
/**
* 发送一个消息,制定字体和字体颜色
* @param message 消息
* @param receiver 接受者QQ号
* @param fontName 字体
* @param size 字体大小,最大是31
* @param bold 是否粗体
* @param italic 是否斜体
* @param underline 是否下划线
* @param red 颜色Red
* @param green 颜色Green
* @param blue 颜色Blue
* @param replyType 回复类型,自动回复还是正常回复
*/
public void sendMessage(String message, int receiver, String fontName, int size, boolean bold, boolean italic, boolean underline, int red, int green, int blue, byte replyType) {
if(user.isLoggedIn()) {
if(message.length() > QQ.QQ_MSG_IM_MAX) return;
SendIMPacket packet = new SendIMPacket();
packet.setReceiver(receiver);
packet.setMessage(message);
packet.setFontName(fontName);
packet.setFontSize((byte)(size & 0xFF));
packet.setRed((byte)(red & 0xFF));
packet.setGreen((byte)(green & 0xFF));
packet.setBlue((byte)(blue & 0xFF));
packet.setBold(bold);
packet.setItalic(italic);
packet.setUnderline(underline);
packet.setReplyType(replyType);
monitor.putRequest(packet);
port.add(packet);
}
}
/**
* @param loginServer
* 登陆服务器IP
*/
public void setLoginServer(String loginServer) {
this.loginServer = loginServer;
}
/**
* @param user The user to set.
*/
public void setUser(QQUser user) {
this.user = user;
Packet.setUser(user);
}
/**
* @param autoGetFriend The autoGetFriend to set.
*/
public void setAutoGetFriend(boolean autoGetFriend) {
this.autoGetFriend = autoGetFriend;
}
/**
* @return Returns the logging.
*/
public boolean isLogging() {
return logging;
}
/**
* @return Returns the port.
*/
public IPort getPort() {
return port;
}
/**
* @param password The password to set.
*/
public void setProxyPassword(String password) {
this.proxyPassword = password;
}
/**
* @param username The username to set.
*/
public void setProxyUsername(String username) {
this.proxyUsername = username;
}
/**
* @param loginRedirect The loginRedirect to set.
*/
public void setLoginRedirect(boolean loginRedirect) {
this.loginRedirect = loginRedirect;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -