/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Project : WebQQCoreAsync Package : iqq.im.module File : ProcModule.java
* Author : solosky < solosky772@qq.com >
* Created : 2012-9-2 License : Apache License 2.0
*/
package iqq.im.module;
import iqq.im.QQActionListener;
import iqq.im.QQException;
import iqq.im.QQException.QQErrorCode;
import iqq.im.bean.QQAccount;
import iqq.im.bean.QQStatus;
import iqq.im.core.QQModule;
import iqq.im.core.QQSession;
import iqq.im.event.QQActionEvent;
import iqq.im.event.QQActionEventArgs;
import iqq.im.event.QQActionFuture;
import iqq.im.event.QQNotifyEvent;
import iqq.im.event.QQNotifyEventArgs;
import iqq.im.event.future.ProcActionFuture;
import java.awt.image.BufferedImage;
import java.util.List;
import org.apache.log4j.Logger;
/**
*
* 处理整体登陆逻辑
*
* @author solosky <solosky772@qq.com>
*
*/
public class ProcModule extends AbstractModule {
private static final Logger LOG = Logger.getLogger(ProcModule.class);
public QQActionFuture login(QQActionListener listener) {
ProcActionFuture future = new ProcActionFuture(listener, true);
doGetLoginSig(future);
return future;
}
public QQActionFuture relogin(QQStatus status, QQActionListener listener) {
LoginModule login = getContext().getModule(QQModule.Type.LOGIN);
return login.channelLogin(status, listener);
}
public QQActionFuture loginWithVerify(String verifyCode, ProcActionFuture future) {
doWebLogin(verifyCode, future);
return future;
}
private void doGetLoginSig(final ProcActionFuture future) {
LoginModule login = (LoginModule) getContext().getModule(QQModule.Type.LOGIN);
login.getLoginSig(new QQActionListener() {
@Override
public void onActionEvent(QQActionEvent event) {
if (event.getType() == QQActionEvent.Type.EVT_OK) {
doCheckVerify(future);
} else if (event.getType() == QQActionEvent.Type.EVT_ERROR) {
future.notifyActionEvent(
QQActionEvent.Type.EVT_ERROR,
(QQException) event.getTarget());
}
}
});
}
private void doGetVerify(final String reason, final ProcActionFuture future) {
if (future.isCanceled()) {
return;
}
QQAccount account = getContext().getAccount();
LoginModule login = (LoginModule) getContext().getModule(QQModule.Type.LOGIN);
login.getCaptcha(account.getUin(), new QQActionListener() {
public void onActionEvent(QQActionEvent event) {
if (event.getType() == QQActionEvent.Type.EVT_OK) {
QQNotifyEventArgs.ImageVerify verify = new QQNotifyEventArgs.ImageVerify();
verify.type = QQNotifyEventArgs.ImageVerify.VerifyType.LOGIN;
verify.image = (BufferedImage) event.getTarget();
verify.reason = reason;
verify.future = future;
getContext().fireNotify(new QQNotifyEvent(QQNotifyEvent.Type.CAPACHA_VERIFY, verify));
} else if (event.getType() == QQActionEvent.Type.EVT_ERROR) {
future.notifyActionEvent(
QQActionEvent.Type.EVT_ERROR,
(QQException) event.getTarget());
}
}
});
}
private void doCheckVerify(final ProcActionFuture future) {
if (future.isCanceled()) {
return;
}
LoginModule login = getContext().getModule(QQModule.Type.LOGIN);
final QQAccount account = getContext().getAccount();
login.checkVerify(account.getUsername(), new QQActionListener() {
public void onActionEvent(QQActionEvent event) {
if (event.getType() == QQActionEvent.Type.EVT_OK) {
QQActionEventArgs.CheckVerifyArgs args
= (QQActionEventArgs.CheckVerifyArgs) (event.getTarget());
account.setUin(args.uin);
if (args.result == 0) {
doWebLogin(args.code, future);
} else {
doGetVerify("为了保证您账号的安全,请输入验证码中字符继续登录。", future);
}
} else if (event.getType() == QQActionEvent.Type.EVT_ERROR) {
future.notifyActionEvent(
QQActionEvent.Type.EVT_ERROR,
(QQException) event.getTarget());
}
}
});
}
private void doWebLogin(String verifyCode, final ProcActionFuture future) {
LoginModule login = getContext().getModule(QQModule.Type.LOGIN);
QQAccount account = getContext().getAccount();
login.webLogin(account.getUsername(), account.getPassword(),
account.getUin(), verifyCode, new QQActionListener() {
public void onActionEvent(QQActionEvent event) {
if (event.getType() == QQActionEvent.Type.EVT_OK) {
doCheckLoginSig((String) event.getTarget(), future);
} else if (event.getType() == QQActionEvent.Type.EVT_ERROR) {
QQException ex = (QQException) (event.getTarget());
if (ex.getError() == QQErrorCode.WRONG_CAPTCHA) {
doGetVerify(ex.getMessage(), future);
} else {
future.notifyActionEvent(
QQActionEvent.Type.EVT_ERROR,
(QQException) event.getTarget());
}
}
}
});
}
private void doCheckLoginSig(String checkSigUrl, final ProcActionFuture future) {
LoginModule login = getContext().getModule(QQModule.Type.LOGIN);
login.checkLoginSig(checkSigUrl, new QQActionListener() {
@Override
public void onActionEvent(QQActionEvent event) {
if (event.getType() == QQActionEvent.Type.EVT_OK) {
doChannelLogin(future);
} else if (event.getType() == QQActionEvent.Type.EVT_ERROR) {
future.notifyActionEvent(
QQActionEvent.Type.EVT_ERROR,
(QQException) event.getTarget());
}
}
});
}
private void doChannelLogin(final ProcActionFuture future) {
LoginModule login = getContext().getModule(QQModule.Type.LOGIN);
login.channelLogin(getContext().getAccount().getStatus(), new QQActionListener() {
public void onActionEvent(QQActionEvent event) {
if (event.getType() == QQActionEvent.Type.EVT_OK) {
future.notifyActionEvent(QQActionEvent.Type.EVT_OK, null);
} else if (event.getType() == QQActionEvent.Type.EVT_ERROR) {
future.notifyActionEvent(QQActionEvent.Type.EVT_ERROR,
(QQException) event.getTarget());
}
}
});
}
public void doPollMsg() {
final LoginModule login = getContext().getModule(QQModule.Type.LOGIN);
login.pollMsg(new QQActionListener() {
public void onActionEvent(QQActionEvent event) {
// 回调通知事件函数
if (event.getType() == QQActionEvent.Type.EVT_OK) {
List<QQNotifyEvent> events = (List<QQNotifyEvent>) event.getTarget();
for (QQNotifyEvent evt : events) {
if (evt.getType() == QQNotifyEvent.Type.NEED_REAUTH) {
relogin(getContext().getAccount().getStatus(), null);
}
getContext().fireNotify(evt);
}
// 准备提交下次poll请求
QQSession session = getContext().getSession();
if (session.getState() == QQSession.State.ONLINE) {
doPollMsg();
}
} else if (event.getType() == QQActionEvent.Type.EVT_ERROR) {
QQSession session = getContext().getSession();
QQAccount account = getContext().getAccount();
session.setState(QQSession.State.OFFLINE);
account.setStatus(QQStatus.OFFLINE);
//因为自带了错误重试机制,如果出现了错误回调,表明已经超时多次均失败,这里直接返回网络错误的异常
QQException ex = (QQException) event.getTarget();
QQErrorCode code = ex.getError();
//粗线了IO异常,直接报网络错误
if (code == QQErrorCode.IO_ERROR || code == QQErrorCode.IO_TIMEOUT) {
getContext().fireNotify(new QQNotifyEvent(QQNotifyEvent.Type.NET_ERROR, ex));
} else {
LOG.warn("poll msg unexpected error, ignore it ...", ex);
doPollMsg();
}
} else if (event.getType() == QQActionEvent.Type.EVT_RETRY) {
System.err.println("Poll Retry:" + this);
LOG.warn("poll msg error, retrying....", (QQException) event.getTarget());
}
}
});
}
public QQActionFuture doLogout(QQActionListener listener) {
LoginModule login = (LoginModule) getContext().getModule(QQModule.Type.LOGIN);
return login.logout(listener);
}
}