您的位置:首页 > 其它

iQQ 学习笔记2 :借助新浪微博输入验证码、远程控制退出

2014-05-31 00:12 603 查看
iQQ 学习笔记2说明 :借助新浪微博输入验证码、远程控制退出
在第1个案例中实现了iQQ的登录、验证码和收消息,其中有两处需要人工参与,第一处是需要打开验证码图片,然后输入验证码,第二处是退出程序需要强制退出。验证码暂时还不能自动识别,不过可以改进交互方式,本例中将借助新浪微博实现显示验证码图片和输入验证码。退出程序改成收到QQ消息后按消息内容操作。
iQQ 学习笔记2程序 :借助新浪微博输入验证码、远程控制退出
这是主程序,其中的username常量的值应替换为QQ号,password常量的值应替换为该QQ号对应的QQ密码。

package test_2;

import java.util.logging.Logger;

import iqq.im.QQClient;

import iqq.im.QQException;

import iqq.im.QQNotifyListener;

import iqq.im.WebQQClient;

import iqq.im.actor.ThreadActorDispatcher;

import iqq.im.bean.QQMsg;

import iqq.im.bean.QQStatus;

import iqq.im.bean.content.ContentItem;

import iqq.im.bean.content.TextItem;

import iqq.im.event.QQActionEvent;

import iqq.im.event.QQActionFuture;

import iqq.im.event.QQNotifyEvent;

import iqq.im.event.QQNotifyEventArgs;

import iqq.im.event.QQActionEvent.Type;

public class Test_2 {

        private static final String username = "**********";

        private static final String password = "**********";

        private static final Logger logger = java.util.logging.Logger.getLogger("");

        private static QQClient client;

        public static void main(String[] args) {

                client = new WebQQClient(username, password, new QQNotifyListener() {

                        @Override

                        public void onNotifyEvent(QQNotifyEvent event) {

                                if (event.getType() == QQNotifyEvent.Type.CHAT_MSG) {

                                        if (event.getTarget() instanceof QQMsg) {

                                                QQMsg msg = (QQMsg) event.getTarget();

                                                for (ContentItem contentItem : msg.getContentList()) {

                                                        if (contentItem instanceof TextItem) {

                                                                TextItem textItem = (TextItem) contentItem;

                                                                logger.info(textItem.getContent());

                                                                if (textItem.getContent().startsWith("logout ")) {

                                                                        client.logout(null);

                                                                }                                                                        

                                                        }

                                                }

                                        }

                                } else if (event.getType() == QQNotifyEvent.Type.CAPACHA_VERIFY) {

                                        if (event.getTarget() instanceof QQNotifyEventArgs.ImageVerify) {

                                                QQNotifyEventArgs.ImageVerify imageVerify = (QQNotifyEventArgs.ImageVerify) event.getTarget();

                                                String code = ImageVerifyQuestioners.ImageVeiryQuestion(imageVerify);

                                                client.submitVerify(code, event);

                                        } else {

                                                logger.info(event.getTarget().getClass().getName());

                                        }

                                } else {

                                        logger.info("TODO QQNotifyEvent: " + event.getType() + ", " + event.getTarget());

                                }

                        }

                }, new ThreadActorDispatcher());

                QQActionFuture future = client.login(QQStatus.ONLINE, null);

                try {

                        QQActionEvent event = future.waitFinalEvent();

                        if (event.getType() == Type.EVT_OK) {

                                client.beginPollMsg();

                        }

                } catch (QQException e) {

                        e.printStackTrace();

                }

        }

}

复制代码
为了便于实现多种图片验证码的输入方式,设计一个图片验证码接口。

package test_2;

import iqq.im.event.QQNotifyEventArgs.ImageVerify;

public abstract class ImageVerifyQuestioner {

        private ImageVerify imageVerify;

        private String Code;

        public ImageVerifyQuestioner(ImageVerify imageVerify) {

                this.imageVerify = imageVerify;

                this.Code = "";

        }

        protected final ImageVerify getImageVerify() {

                return imageVerify;

        }

        public final String getCode() {

                return Code;

        }

        protected final void setCode(String code) {

                Code = code;

        }

        public abstract void loop ();

}

复制代码
通过一个调度程序管理多种图片验证码的输入方式,当一种输入方式获取验证码时,其他输入方式退出。

package test_2;

import java.util.ArrayList;

import java.util.List;

import iqq.im.event.QQNotifyEventArgs.ImageVerify;

public class ImageVerifyQuestioners {

        public static String ImageVeiryQuestion (ImageVerify imageVerify) {

                String code = "";

                List<ImageVerifyQuestioner> imageVerifyQuestionerList = new ArrayList<ImageVerifyQuestioner>();

                imageVerifyQuestionerList.add(new ImageVerifyConsoleQuestioner(imageVerify));

                imageVerifyQuestionerList.add(new ImageVerifyWeiboQuestioner(imageVerify));

                boolean alive = true;

                while (alive) {

                        for(ImageVerifyQuestioner imageVerifyQuestioner : imageVerifyQuestionerList) {

                                if (true == alive) {

                                        imageVerifyQuestioner.loop();

                                        if (imageVerifyQuestioner.getCode() != "") {

                                                code = imageVerifyQuestioner.getCode();

                                                alive = false;

                                        }                                        

                                }

                        }

                        try {

                                Thread.sleep(100);

                        } catch (InterruptedException e) {

                                e.printStackTrace();

                        }

                }

                return code;

        }

}

复制代码
保持原有的命令行交互输入图片验证码的输入方式。

/**



*/

package test_2;

import java.io.File;

import java.io.IOException;

import javax.imageio.ImageIO;

import iqq.im.event.QQNotifyEventArgs.ImageVerify;

public class ImageVerifyConsoleQuestioner extends ImageVerifyQuestioner {

        private boolean isPrompt;

        private StringBuilder codeStringBuilder = new StringBuilder();

        public ImageVerifyConsoleQuestioner(ImageVerify imageVerify) {

                super(imageVerify);

        }

        private void prompt () {

                try {

                        ImageIO.write(this.getImageVerify().image, "png", new File("verify.png"));

                        System.out.println(this.getImageVerify().reason);

                        System.out.print("请输入在项目根目录下 verify.png 图片里面的验证码: ");

                        isPrompt = true;

                } catch (IOException e) {

                        e.printStackTrace();

                }

        }

        private void read () {

                try {

                        int available = System.in.available();

                        if (0 < available) {

                                int inChar = System.in.read();

                                switch (Character.getType(inChar)) {

                                case Character.UPPERCASE_LETTER:

                                case Character.LOWERCASE_LETTER:

                                case Character.DECIMAL_DIGIT_NUMBER:

                                        codeStringBuilder.append((char) inChar);

                                        break;

                                case Character.CONTROL:

                                        this.setCode(codeStringBuilder.toString());

                                        break;

                                }

                        }

                } catch (IOException e) {

                        e.printStackTrace();

                }

        }

        @Override

        public void loop() {

                if (false == this.isPrompt) {

                        this.prompt();

                }

                if (this.getCode() == "") {

                        this.read();                                        

                }                

        }

}

复制代码
新增通过新浪微博输入图片验证码的输入方式,其中的accessTokenFile的值应替换为保存新浪微博Access Token的路径。

/**



*/

package test_2;

import java.io.BufferedReader;

import java.io.ByteArrayOutputStream;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.MalformedURLException;

import java.net.URL;

import java.net.URLConnection;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.logging.Logger;

import javax.imageio.ImageIO;

import javax.net.ssl.HttpsURLConnection;

import org.json.JSONObject;

import iqq.im.event.QQNotifyEventArgs.ImageVerify;

public class ImageVerifyWeiboQuestioner extends ImageVerifyQuestioner {

        private static final String accessTokenFile = "**********";

        private static final Logger logger = java.util.logging.Logger.getLogger("");

        private String accessToken;

        private long weiboId;

        private long lastCheckTime;

        public ImageVerifyWeiboQuestioner(ImageVerify imageVerify) {

                super(imageVerify);

        }

        private void readAccessToken () {

                FileReader fileReaderAccessToken;

                try {

                        fileReaderAccessToken = new FileReader(accessTokenFile);

                        BufferedReader bufferedReaderAccessToken = new BufferedReader(fileReaderAccessToken);

                        accessToken = bufferedReaderAccessToken.readLine();

                        bufferedReaderAccessToken.close();

                        fileReaderAccessToken.close();

                } catch (FileNotFoundException e) {

                        e.printStackTrace();

                } catch (IOException e) {

                        e.printStackTrace();

                }

        }

        private void uploadVerifyImage () {

                try {

                        //Status

                        StringBuilder statusStringBuilder = new StringBuilder();

                        statusStringBuilder.append("请@胡争辉 输入验证码 ");

                        statusStringBuilder.append((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date())); 

                        //URL

                        StringBuilder urlStringBuilder = new StringBuilder();

                        urlStringBuilder.append("https://api.weibo.com/2/statuses/upload.json?access_token=");

                        urlStringBuilder.append(accessToken);

                        URL url = new URL(urlStringBuilder.toString());

                        URLConnection urlConnection =url.openConnection();

                        if (urlConnection instanceof HttpsURLConnection) {

                                String BOUNDARY = "---------------------------" + String.valueOf(System.currentTimeMillis());

                                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

                                byteArrayOutputStream.write(("--" + BOUNDARY + "\r\n").getBytes());

                                byteArrayOutputStream.write(("Content-Disposition: form-data; name=\"pic\"; filename=\"verifyimage.png\"\r\n").getBytes());

                                byteArrayOutputStream.write(("Content-Type: image/png\r\n").getBytes());

                                byteArrayOutputStream.write(("\r\n").getBytes());

                                ImageIO.write(this.getImageVerify().image, "png", byteArrayOutputStream);

                                byteArrayOutputStream.write(("\r\n").getBytes());

                                byteArrayOutputStream.write(("--" + BOUNDARY + "\r\n").getBytes());

                                byteArrayOutputStream.write(("Content-Disposition: form-data; name=\"status\"\r\n").getBytes());

                                byteArrayOutputStream.write(("\r\n").getBytes());

                                byteArrayOutputStream.write(statusStringBuilder.toString().getBytes());

                                byteArrayOutputStream.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes());

                                HttpsURLConnection httpsURLConnection = (HttpsURLConnection) urlConnection;

                                httpsURLConnection.setRequestMethod("POST");

                                httpsURLConnection.addRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

                                httpsURLConnection.setDoOutput(true);

                                httpsURLConnection.setDoInput(true);

                                OutputStream outputStream = httpsURLConnection.getOutputStream();

                                outputStream.write(byteArrayOutputStream.toByteArray());

                                outputStream.flush();

                                outputStream.close();

                                StringBuilder response = new StringBuilder();

                                InputStreamReader inputStreamReader = new InputStreamReader(httpsURLConnection.getInputStream());

                                int readChar = inputStreamReader.read();

                                while (-1 != readChar) {

                                        response.append((char) readChar);

                                        readChar = inputStreamReader.read();

                                }

                                inputStreamReader.close();

                                httpsURLConnection.disconnect();

                                logger.info(response.toString());

                                JSONObject responseJson = new JSONObject(response.toString());

                                this.weiboId = responseJson.getLong("id"); 

                                logger.info("Weibo Id = " + String.valueOf(this.weiboId));

                        }

                } catch (FileNotFoundException e) {

                        e.printStackTrace();

                } catch (IOException e) {

                        e.printStackTrace();

                }

                

        }

        private void checkComment () {

                try {

                        StringBuilder commentStringBuilder = new StringBuilder();

                        commentStringBuilder.append("https://api.weibo.com/2/comments/show.json?filter_by_author=1&access_token=");

                        commentStringBuilder.append(accessToken);

                        commentStringBuilder.append("&id=");

                        commentStringBuilder.append(weiboId);

                        URL comment = new URL(commentStringBuilder.toString());

                        URLConnection commentConnection = comment.openConnection();

                        if (commentConnection instanceof HttpsURLConnection) {

                                HttpsURLConnection commentHttpsURLConnection = (HttpsURLConnection) commentConnection;

                                commentHttpsURLConnection.setDoInput(true);

                                InputStreamReader commentStreamReader = new InputStreamReader(commentHttpsURLConnection.getInputStream());

                                StringBuilder commentResponse = new StringBuilder();

                                int commentChar = commentStreamReader.read();

                                while (-1 != commentChar) {

                                        commentResponse.append((char) commentChar);

                                        commentChar = commentStreamReader.read();

                                }

                                commentStreamReader.close();

                                commentHttpsURLConnection.disconnect();

                                JSONObject commentsJson = new JSONObject(commentResponse.toString());

                                int total_number = commentsJson.getInt("total_number");

                                logger.info("total_number = " + String.valueOf(total_number));

                                if (0 < total_number) {

                                        JSONObject commentJson = commentsJson.getJSONArray("comments").getJSONObject(0);

                                        logger.info("text=" + commentJson.getString("text"));

                                        this.setCode(commentJson.getString("text"));

                                }

                                

                        }

                } catch (MalformedURLException e) {

                        e.printStackTrace();

                } catch (IOException e) {

                        e.printStackTrace();

                }

        }

        @Override

        public void loop () {

                if (null == accessToken) {

                        this.readAccessToken();

                }

                if ((null != accessToken) && (0 == weiboId)) {

                        this.uploadVerifyImage();

                        lastCheckTime = System.currentTimeMillis();

                }

                if ((0 < weiboId) && (this.getCode() == "") && (10000 < System.currentTimeMillis() - lastCheckTime)) {

                        this.checkComment();

                        lastCheckTime = System.currentTimeMillis();

                }

        }

}

复制代码
iQQ 学习笔记2测试 :借助新浪微博输入验证码、远程控制退出
测试本程序需要注册两个QQ号,并互相加为好友。保持一个QQ使用客户端登录,另一个QQ的QQ号和密码填写在程序中。
需要注册一个新浪微博APP帐号,需要注册两个新浪微博帐号,其中一个通过该新浪微博APP验证后保存Access Token,设定这两个帐号互相关注。
运行程序后不仅出现命令行提示,还将用一个新浪微博帐号发一条微博,另一个新浪微博帐号会显示该条微博,微博上包含有验证码图片,用另一个新浪微博帐号回复该条微博,内容为验证码图片上的文字。
在QQ上可以看到该QQ上线,如果输入logout,QQ将下线,程序自动退出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: