From 8cbb70479ad93a4344064b62abb416c7441d6390 Mon Sep 17 00:00:00 2001 From: yaphone Date: Fri, 12 May 2017 00:49:08 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E6=B7=BB=E5=8A=A0logger4j?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 23 +++-- .../zhouyafeng/itchat4j/components/Login.java | 86 +++++++++++++------ src/main/resources/config/Log4j.properties | 9 ++ .../zhouyafeng/itchat4j/demo/SimpleDemo.java | 5 ++ 4 files changed, 89 insertions(+), 34 deletions(-) create mode 100644 src/main/resources/config/Log4j.properties diff --git a/pom.xml b/pom.xml index afa0478..3d0cd42 100644 --- a/pom.xml +++ b/pom.xml @@ -16,13 +16,7 @@ - - junit - junit - 3.8.1 - test - - + org.apache.httpcomponents @@ -64,6 +58,21 @@ 1.1.1 + + + junit + junit + 4.12 + + + + + log4j + log4j + 1.2.17 + + + diff --git a/src/main/java/cn/zhouyafeng/itchat4j/components/Login.java b/src/main/java/cn/zhouyafeng/itchat4j/components/Login.java index 3e00a13..f35743a 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/components/Login.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/components/Login.java @@ -383,29 +383,50 @@ void startReceiving() { public void run() { while (core.isAlive()) { try { - String i = syncCheck(); - if (i == null) { - core.setAlive(false); - } else if (i.equals("0")) { + Map resultMap = syncCheck(); + String retcode = resultMap.get("retcode"); + String selector = resultMap.get("selector"); + if (retcode.equals("9999")) { continue; - } else { - JSONArray msgList = new JSONArray(); - JSONObject msgObj = getMsg(); - if (msgObj != null) { - msgList = msgObj.getJSONArray("AddMsgList"); - msgList = MessageTools.produceMsg(msgList); - for (int j = 0; j < msgList.size(); j++) { - core.getMsgList().add(msgList.getJSONObject(j)); + } else if (retcode.equals("1100")) { // 退出 + logger.info("login out"); + break; + } else if (retcode.equals("1101")) { // 其它地方登陆 + logger.info("login otherwhere"); + break; + } else if (retcode.equals("1102")) { // 移动端退出 + logger.info("login quit on phone"); + break; + } else if (retcode.equals("0")) { + if (selector.equals("2")) { + JSONObject msgObj = webWxSync(); + if (msgObj != null) { + try { + JSONArray msgList = new JSONArray(); + msgList = msgObj.getJSONArray("AddMsgList"); + msgList = MessageTools.produceMsg(msgList); + for (int j = 0; j < msgList.size(); j++) { + core.getMsgList().add(msgList.getJSONObject(j)); + } + } catch (Exception e) { + logger.info(e.getMessage()); + } + } else if (selector.equals("7")) { + webWxSync(); + } else if (selector.equals("4")) { + // 保存群聊到通讯录 + // 修改群名称 + // 新增或删除联系人 + // 群聊成员数目变化 + // TODO + } else if (selector.equals("3") || selector.equals("6")) { + break; } - - // TODO chatroomMsg = - // update_local_chatrooms(self, chatroomList) - // TODO self.msgList.put(chatroomMsg) - // TODO update_local_friends(self, otherList) } + } else { + JSONObject obj = webWxSync(); + logger.info(obj.toJSONString()); } - retryCount = 0; - } catch (Exception e) { logger.info(e.getMessage()); retryCount += 1; @@ -426,14 +447,15 @@ public void run() { } /** - * 保活心跳 + * 检查是否有新消息 check whether there's a message * * @author https://github.com/yaphone * @date 2017年4月16日 上午11:11:34 * @return + * */ - String syncCheck() { - String result = null; + private Map syncCheck() { + Map resultMap = new HashMap(); String syncUrl = (String) core.getLoginInfo().get("syncUrl"); // String syncUrl = "https://webpush.wx2.qq.com/cgi-bin/mmwebwx-bin"; if (syncUrl == null || syncUrl.equals("")) { @@ -451,7 +473,9 @@ String syncCheck() { try { HttpEntity entity = myHttpClient.doGet(url, params, true, null); if (entity == null) { - return "0"; + resultMap.put("retcode", "9999"); + resultMap.put("selector", "9999"); + return resultMap; } String text = EntityUtils.toString(entity); String regEx = "window.synccheck=\\{retcode:\"(\\d+)\",selector:\"(\\d+)\"\\}"; @@ -459,16 +483,24 @@ String syncCheck() { if (!matcher.find() || matcher.group(1).equals("2")) { logger.info(String.format("Unexpected sync check result: %s", text)); } else { - result = matcher.group(2); + resultMap.put("retcode", matcher.group(1)); + resultMap.put("selector", matcher.group(2)); } } catch (Exception e) { e.printStackTrace(); } - return result; + return resultMap; } - JSONObject getMsg() { - JSONObject result = new JSONObject(); + /** + * 同步消息 sync the messages + * + * @author https://github.com/yaphone + * @date 2017年5月12日 上午12:24:55 + * @return + */ + JSONObject webWxSync() { + JSONObject result = null; String url = String.format("%s/webwxsync?sid=%s&skey=%s&pass_ticket=%s", core.getLoginInfo().get("url"), core.getLoginInfo().get("wxsid"), core.getLoginInfo().get("skey"), core.getLoginInfo().get("pass_ticket")); diff --git a/src/main/resources/config/Log4j.properties b/src/main/resources/config/Log4j.properties new file mode 100644 index 0000000..829e45d --- /dev/null +++ b/src/main/resources/config/Log4j.properties @@ -0,0 +1,9 @@ +# Define the root logger with appender X +Log4j.rootLogger = DEBUG, X + +# Set the appender named X to be a File appender +Log4j.appender.X=org.apache.Log4j.FileAppender + +# Define the layout for X appender +Log4j.appender.X.layout=org.apache.Log4j.PatternLayout +Log4j.appender.X.layout.conversionPattern=%m%n \ No newline at end of file diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java index 40f9e8a..5e19b8f 100644 --- a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java @@ -4,6 +4,8 @@ import java.text.SimpleDateFormat; import java.util.Date; +import org.apache.log4j.Logger; + import com.alibaba.fastjson.JSONObject; import cn.zhouyafeng.itchat4j.Wechat; @@ -20,6 +22,7 @@ * */ public class SimpleDemo implements IMsgHandlerFace { + Logger logger = Logger.getLogger(SimpleDemo.class); @Override public String textMsgHandle(JSONObject msg) { @@ -31,6 +34,8 @@ public String textMsgHandle(JSONObject msg) { // MessageTools.sendFileMsgByNickName("yaphone", pngFilePath); // MessageTools.sendFileMsgByNickName("yaphone", pdfFilePath); // MessageTools.sendFileMsgByNickName("yaphone", txtFilePath); + logger.info("info" + msg.toJSONString()); + logger.debug("info" + msg.toJSONString()); String text = msg.getString("Text"); return text; // return null; From 7145d71468b75eb643f0f116a4f0c96db4f40e54 Mon Sep 17 00:00:00 2001 From: yaphone Date: Fri, 12 May 2017 01:17:38 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E6=B7=BB=E5=8A=A0logger4j?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- logContentFile.log | 0 pom.xml | 20 ++++++++++++++----- src/main/java/log4j.properties | 11 ++++++++++ src/main/resources/config/Log4j.properties | 9 --------- .../zhouyafeng/itchat4j/demo/SimpleDemo.java | 5 +++-- 5 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 logContentFile.log create mode 100644 src/main/java/log4j.properties delete mode 100644 src/main/resources/config/Log4j.properties diff --git a/logContentFile.log b/logContentFile.log new file mode 100644 index 0000000..e69de29 diff --git a/pom.xml b/pom.xml index 3d0cd42..12430ed 100644 --- a/pom.xml +++ b/pom.xml @@ -66,11 +66,21 @@ - - log4j - log4j - 1.2.17 - + + org.slf4j + slf4j-api + 1.6.6 + + + org.slf4j + slf4j-log4j12 + 1.6.6 + + + log4j + log4j + 1.2.16 + diff --git a/src/main/java/log4j.properties b/src/main/java/log4j.properties new file mode 100644 index 0000000..3cee63d --- /dev/null +++ b/src/main/java/log4j.properties @@ -0,0 +1,11 @@ +#config root logger +log4j.rootLogger = INFO,system.out +log4j.appender.system.out=org.apache.log4j.ConsoleAppender +log4j.appender.system.out.layout=org.apache.log4j.PatternLayout +log4j.appender.system.out.layout.ConversionPattern=MINAServer Logger-->%5p{%F:%L}-%m%n + +#config this Project.file logger +log4j.logger.thisProject.file=ALL,thisProject.file.out +log4j.appender.thisProject.file.out=org.apache.log4j.DailyRollingFileAppender +log4j.appender.thisProject.file.out.File=logContentFile.log +log4j.appender.thisProject.file.out.layout=org.apache.log4j.PatternLayout \ No newline at end of file diff --git a/src/main/resources/config/Log4j.properties b/src/main/resources/config/Log4j.properties deleted file mode 100644 index 829e45d..0000000 --- a/src/main/resources/config/Log4j.properties +++ /dev/null @@ -1,9 +0,0 @@ -# Define the root logger with appender X -Log4j.rootLogger = DEBUG, X - -# Set the appender named X to be a File appender -Log4j.appender.X=org.apache.Log4j.FileAppender - -# Define the layout for X appender -Log4j.appender.X.layout=org.apache.Log4j.PatternLayout -Log4j.appender.X.layout.conversionPattern=%m%n \ No newline at end of file diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java index 5e19b8f..5196a5a 100644 --- a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java @@ -34,8 +34,9 @@ public String textMsgHandle(JSONObject msg) { // MessageTools.sendFileMsgByNickName("yaphone", pngFilePath); // MessageTools.sendFileMsgByNickName("yaphone", pdfFilePath); // MessageTools.sendFileMsgByNickName("yaphone", txtFilePath); - logger.info("info" + msg.toJSONString()); - logger.debug("info" + msg.toJSONString()); + // logger.info("info" + msg.toJSONString()); + // System.out.println("*************"); + logger.info("debug" + msg.toJSONString()); String text = msg.getString("Text"); return text; // return null; From e0851fb57a1bc6c431d7e36cfe03958b93aff92b Mon Sep 17 00:00:00 2001 From: yaphone Date: Fri, 12 May 2017 23:51:38 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=8C=85=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/zhouyafeng/itchat4j/Wechat.java | 15 +- .../zhouyafeng/itchat4j/api/MessageTools.java | 100 +------------ .../zhouyafeng/itchat4j/api/WechatTools.java | 13 +- .../itchat4j/components/Contact.java | 12 -- .../zhouyafeng/itchat4j/components/Login.java | 23 ++- .../zhouyafeng/itchat4j/core/MsgCenter.java | 98 +++++++++++++ .../cn/zhouyafeng/itchat4j/utils/Config.java | 25 ++-- .../zhouyafeng/itchat4j/utils/Constant.java | 6 - .../cn/zhouyafeng/itchat4j/utils/Contact.java | 89 ------------ .../cn/zhouyafeng/itchat4j/utils/Core.java | 77 +++++----- .../itchat4j/utils/DownloadTools.java | 70 --------- .../cn/zhouyafeng/itchat4j/utils/Storage.java | 136 ------------------ .../{OsName.java => enums/OsNameEnum.java} | 4 +- .../{ => utils}/tools/CommonTool.java | 14 +- .../{ => utils}/tools/DownloadTools.java | 2 +- src/main/{java => resources}/log4j.properties | 0 .../zhouyafeng/itchat4j/demo/SimpleDemo.java | 2 +- .../zhouyafeng/itchat4j/demo/TulingRobot.java | 2 +- 18 files changed, 188 insertions(+), 500 deletions(-) delete mode 100644 src/main/java/cn/zhouyafeng/itchat4j/components/Contact.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java delete mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/Constant.java delete mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/Contact.java delete mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/DownloadTools.java delete mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/Storage.java rename src/main/java/cn/zhouyafeng/itchat4j/utils/{OsName.java => enums/OsNameEnum.java} (72%) rename src/main/java/cn/zhouyafeng/itchat4j/{ => utils}/tools/CommonTool.java (94%) rename src/main/java/cn/zhouyafeng/itchat4j/{ => utils}/tools/DownloadTools.java (98%) rename src/main/{java => resources}/log4j.properties (100%) diff --git a/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java b/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java index f091066..09848e4 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java @@ -47,19 +47,24 @@ public void run() { if (msg.getString("Type") != null) { if (msg.getString("Type").equals(MsgType.TEXT)) { String result = msgHandler.textMsgHandle(msg); - MessageTools.send(result, core.getMsgList().get(0).getString("FromUserName"), ""); + MessageTools.sendMsgById(result, + core.getMsgList().get(0).getString("FromUserName")); } else if (msg.getString("Type").equals(MsgType.PIC)) { String result = msgHandler.picMsgHandle(msg); - MessageTools.send(result, core.getMsgList().get(0).getString("FromUserName"), ""); + MessageTools.sendMsgById(result, + core.getMsgList().get(0).getString("FromUserName")); } else if (msg.getString("Type").equals(MsgType.VOICE)) { String result = msgHandler.voiceMsgHandle(msg); - MessageTools.send(result, core.getMsgList().get(0).getString("FromUserName"), ""); + MessageTools.sendMsgById(result, + core.getMsgList().get(0).getString("FromUserName")); } else if (msg.getString("Type").equals(MsgType.VIEDO)) { String result = msgHandler.viedoMsgHandle(msg); - MessageTools.send(result, core.getMsgList().get(0).getString("FromUserName"), ""); + MessageTools.sendMsgById(result, + core.getMsgList().get(0).getString("FromUserName")); } else if (msg.getString("Type").equals(MsgType.NAMECARD)) { String result = msgHandler.nameCardMsgHandle(msg); - MessageTools.send(result, core.getMsgList().get(0).getString("FromUserName"), ""); + MessageTools.sendMsgById(result, + core.getMsgList().get(0).getString("FromUserName")); } } } diff --git a/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java b/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java index 2ea0a00..9ff1e2b 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java @@ -7,7 +7,6 @@ import java.util.Map; import java.util.Random; import java.util.logging.Logger; -import java.util.regex.Matcher; import javax.activation.MimetypesFileTypeMap; @@ -18,13 +17,10 @@ import org.apache.http.util.EntityUtils; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import cn.zhouyafeng.itchat4j.tools.CommonTool; -import cn.zhouyafeng.itchat4j.utils.Constant; +import cn.zhouyafeng.itchat4j.utils.Config; import cn.zhouyafeng.itchat4j.utils.Core; -import cn.zhouyafeng.itchat4j.utils.MsgType; import cn.zhouyafeng.itchat4j.utils.MyHttpClient; /** @@ -40,88 +36,6 @@ public class MessageTools { private static Core core = Core.getInstance(); private static MyHttpClient myHttpClient = core.getMyHttpClient(); - /** - * 接收消息,放入队列 - * - * @author https://github.com/yaphone - * @date 2017年4月23日 下午2:30:48 - * @param msgList - * @return - */ - public static JSONArray produceMsg(JSONArray msgList) { - JSONArray result = new JSONArray(); - for (int i = 0; i < msgList.size(); i++) { - JSONObject msg = new JSONObject(); - JSONObject m = msgList.getJSONObject(i); - m.put("groupMsg", false);// 是否是群消息 - if (m.getString("FromUserName").contains("@@") || m.getString("ToUserName").contains("@@")) { // 群聊消息 - // produceGroupChat(core, m); - // m.remove("Content"); - if (m.getString("FromUserName").contains("@@") - && !core.getGroupIdList().contains(m.getString("FromUserName"))) { - core.getGroupIdList().add((m.getString("FromUserName"))); - } else if (m.getString("ToUserName").contains("@@") - && !core.getGroupIdList().contains(m.getString("ToUserName"))) { - core.getGroupIdList().add((m.getString("ToUserName"))); - } - // 群消息与普通消息不同的是在其消息体(Content)中会包含发送者id及":
"消息,这里需要处理一下,去掉多余信息,只保留消息内容 - if (m.getString("Content").contains("
")) { - String content = m.getString("Content").substring(m.getString("Content").indexOf("
") + 5); - m.put("Content", content); - m.put("groupMsg", true); - } - } else { - CommonTool.msgFormatter(m, "Content"); - } - if (m.getInteger("MsgType") == MsgType.MSGTYPE_TEXT) { // words 文本消息 - if (m.getString("Url").length() != 0) { - String regEx = "(.+?\\(.+?\\))"; - Matcher matcher = CommonTool.getMatcher(regEx, m.getString("Content")); - String data = "Map"; - if (matcher.find()) { - data = matcher.group(1); - } - msg.put("Type", "Map"); - msg.put("Text", data); - } else { - msg.put("Type", MsgType.TEXT); - msg.put("Text", m.getString("Content")); - } - m.put("Type", msg.getString("Type")); - m.put("Text", msg.getString("Text")); - } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_IMAGE - || m.getInteger("MsgType") == MsgType.MSGTYPE_EMOTICON) { // 图片消息 - m.put("Type", MsgType.PIC); - } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_VOICE) { // 语音消息 - m.put("Type", MsgType.VOICE); - } else if (m.getInteger("MsgType") == 37) {// friends 好友确认消息 - - } else if (m.getInteger("MsgType") == 42) { // 共享名片 - m.put("Type", MsgType.NAMECARD); - - } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_VIDEO - || m.getInteger("MsgType") == MsgType.MSGTYPE_MICROVIDEO) {// viedo - m.put("Type", MsgType.VIEDO); - } else if (m.getInteger("MsgType") == 49) { // sharing 分享链接 - - } else if (m.getInteger("MsgType") == 51) {// phone init 微信初始化消息 - - } else if (m.getInteger("MsgType") == 10000) {// 系统消息 - - } else if (m.getInteger("MsgType") == 10002) { // 撤回消息 - - } else { - logger.info("Useless msg"); - } - result.add(m); - } - return result; - } - - public static void send(String msg, String toUserName, String mediaId) { - sendMsg(msg, toUserName); - } - /** * 根据UserName发送文本消息 * @@ -130,7 +44,7 @@ public static void send(String msg, String toUserName, String mediaId) { * @param msg * @param toUserName */ - public static void sendMsg(String text, String toUserName) { + private static void sendMsg(String text, String toUserName) { logger.info(String.format("Request to send a text message to %s: %s", toUserName, text)); sendRawMsg(1, text, toUserName); } @@ -187,8 +101,8 @@ public static void sendRawMsg(int msgType, String content, String toUserName) { Map msgMap = new HashMap(); msgMap.put("Type", msgType); msgMap.put("Content", content); - msgMap.put("FromUserName", core.getStorageClass().getUserName()); - msgMap.put("ToUserName", toUserName == null ? core.getStorageClass().getUserName() : toUserName); + msgMap.put("FromUserName", core.getUserName()); + msgMap.put("ToUserName", toUserName == null ? core.getUserName() : toUserName); msgMap.put("LocalID", new Date().getTime() * 10); msgMap.put("ClientMsgId", new Date().getTime() * 10); paramMap.put("Msg", msgMap); @@ -331,7 +245,7 @@ private static boolean webWxSendMsgImg(String userId, String mediaId) { Map msgMap = new HashMap(); msgMap.put("Type", 3); msgMap.put("MediaId", mediaId); - msgMap.put("FromUserName", core.getUserSelfList().get(0).getString("UserName")); + msgMap.put("FromUserName", core.getUserSelf().getString("UserName")); msgMap.put("ToUserName", userId); String clientMsgId = String.valueOf(new Date().getTime()) + String.valueOf(new Random().nextLong()).substring(1, 5); @@ -369,7 +283,7 @@ private static boolean webWxSendMsgImg(String userId, String mediaId) { public static boolean sendFileMsgByUserId(String userId, String filePath) { String title = new File(filePath).getName(); Map data = new HashMap(); - data.put("appid", Constant.API_WXAPPID); + data.put("appid", Config.API_WXAPPID); data.put("title", title); data.put("totallen", ""); data.put("attachid", ""); @@ -423,7 +337,7 @@ private static boolean webWxSendAppMsg(String userId, Map data) Map msgMap = new HashMap(); msgMap.put("Type", data.get("type")); msgMap.put("Content", content); - msgMap.put("FromUserName", core.getUserSelfList().get(0).getString("UserName")); + msgMap.put("FromUserName", core.getUserSelf().getString("UserName")); msgMap.put("ToUserName", userId); msgMap.put("LocalID", clientMsgId); msgMap.put("ClientMsgId", clientMsgId); diff --git a/src/main/java/cn/zhouyafeng/itchat4j/api/WechatTools.java b/src/main/java/cn/zhouyafeng/itchat4j/api/WechatTools.java index 3061302..7505e82 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/api/WechatTools.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/api/WechatTools.java @@ -28,18 +28,7 @@ public class WechatTools { * @param toUserName */ public static void sendMsgByUserName(String msg, String toUserName) { - MessageTools.sendMsg(msg, toUserName); - } - - /** - * 获取好友列表,JSONObject格式 - * - * @author https://github.com/yaphone - * @date 2017年5月4日 下午10:55:18 - * @return - */ - private static List getJsonContactList() { - return core.getContactList(); + MessageTools.sendMsgById(msg, toUserName); } /** diff --git a/src/main/java/cn/zhouyafeng/itchat4j/components/Contact.java b/src/main/java/cn/zhouyafeng/itchat4j/components/Contact.java deleted file mode 100644 index 34615ef..0000000 --- a/src/main/java/cn/zhouyafeng/itchat4j/components/Contact.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.zhouyafeng.itchat4j.components; - -import com.alibaba.fastjson.JSONArray; - -import cn.zhouyafeng.itchat4j.utils.Core; - -public class Contact { - public static Object updateLocalChatrooms(Core core, JSONArray l) { - // TODO - return null; - } -} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/components/Login.java b/src/main/java/cn/zhouyafeng/itchat4j/components/Login.java index f35743a..e5da21d 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/components/Login.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/components/Login.java @@ -23,18 +23,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import cn.zhouyafeng.itchat4j.api.MessageTools; -import cn.zhouyafeng.itchat4j.tools.CommonTool; +import cn.zhouyafeng.itchat4j.core.MsgCenter; import cn.zhouyafeng.itchat4j.utils.Config; -import cn.zhouyafeng.itchat4j.utils.Contact; import cn.zhouyafeng.itchat4j.utils.Core; import cn.zhouyafeng.itchat4j.utils.MyHttpClient; +import cn.zhouyafeng.itchat4j.utils.tools.CommonTool; public class Login { private static Logger logger = Logger.getLogger("Wechat"); private String baseUrl = Config.BASE_URL; private boolean isLoginIn = false; - private Contact contact = new Contact(); private Core core = Core.getInstance(); @@ -96,9 +94,8 @@ public int login(String qrPath) { } this.webInit(); this.showMobileLogin(); - contact.getContact(true); CommonTool.clearScreen(); - logger.info(String.format("Login successfully as %s", core.getStorageClass().getNickName())); + logger.info(String.format("Login successfully as %s", core.getNickName())); startReceiving(); webWxGetContact(); return 0; @@ -343,9 +340,9 @@ private JSONObject webInit() { } String synckey = sb.toString(); core.getLoginInfo().put("synckey", synckey.substring(0, synckey.length() - 1));// 1_656161336|2_656161626|3_656161313|11_656159955|13_656120033|201_1492273724|1000_1492265953|1001_1492250432|1004_1491805192 - core.getStorageClass().setUserName((obj.getJSONObject("User")).getString("UserName")); - core.getStorageClass().setNickName((obj.getJSONObject("User")).getString("NickName")); - core.getUserSelfList().add(obj.getJSONObject("User")); + core.setUserName((obj.getJSONObject("User")).getString("UserName")); + core.setNickName((obj.getJSONObject("User")).getString("NickName")); + core.setUserSelf(obj.getJSONObject("User")); } catch (Exception e) { e.printStackTrace(); } @@ -362,8 +359,8 @@ private void showMobileLogin() { .get("baseRequest"); paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest")); paramMap.put("Code", 3); - paramMap.put("FromUserName", core.getStorageClass().getUserName()); - paramMap.put("ToUserName", core.getStorageClass().getUserName()); + paramMap.put("FromUserName", core.getUserName()); + paramMap.put("ToUserName", core.getUserName()); paramMap.put("ClientMsgId", String.valueOf(new Date().getTime())); String paramStr = JSON.toJSONString(paramMap); try { @@ -404,7 +401,7 @@ public void run() { try { JSONArray msgList = new JSONArray(); msgList = msgObj.getJSONArray("AddMsgList"); - msgList = MessageTools.produceMsg(msgList); + msgList = MsgCenter.produceMsg(msgList); for (int j = 0; j < msgList.size(); j++) { core.getMsgList().add(msgList.getJSONObject(j)); } @@ -575,7 +572,7 @@ boolean webWxGetContact() { core.getSpecialUsersList().add(o); } else if (o.getString("UserName").indexOf("@@") != -1) { // 群聊 core.getGroupList().add(o); - } else if (o.getString("UserName").equals(core.getUserSelfList().get(0).getString("UserName"))) { // 自己 + } else if (o.getString("UserName").equals(core.getUserSelf().getString("UserName"))) { // 自己 core.getContactList().remove(o); } else { // 普通联系人 core.getContactList().add(o); diff --git a/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java b/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java new file mode 100644 index 0000000..7c57738 --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java @@ -0,0 +1,98 @@ +package cn.zhouyafeng.itchat4j.core; + +import java.util.regex.Matcher; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import cn.zhouyafeng.itchat4j.utils.Core; +import cn.zhouyafeng.itchat4j.utils.MsgType; +import cn.zhouyafeng.itchat4j.utils.tools.CommonTool; + +public class MsgCenter { + private static Logger LOG = LoggerFactory.getLogger(MsgCenter.class); + + private static Core core = Core.getInstance(); + + /** + * 接收消息,放入队列 + * + * @author https://github.com/yaphone + * @date 2017年4月23日 下午2:30:48 + * @param msgList + * @return + */ + public static JSONArray produceMsg(JSONArray msgList) { + JSONArray result = new JSONArray(); + for (int i = 0; i < msgList.size(); i++) { + JSONObject msg = new JSONObject(); + JSONObject m = msgList.getJSONObject(i); + m.put("groupMsg", false);// 是否是群消息 + if (m.getString("FromUserName").contains("@@") || m.getString("ToUserName").contains("@@")) { // 群聊消息 + // produceGroupChat(core, m); + // m.remove("Content"); + if (m.getString("FromUserName").contains("@@") + && !core.getGroupIdList().contains(m.getString("FromUserName"))) { + core.getGroupIdList().add((m.getString("FromUserName"))); + } else if (m.getString("ToUserName").contains("@@") + && !core.getGroupIdList().contains(m.getString("ToUserName"))) { + core.getGroupIdList().add((m.getString("ToUserName"))); + } + // 群消息与普通消息不同的是在其消息体(Content)中会包含发送者id及":
"消息,这里需要处理一下,去掉多余信息,只保留消息内容 + if (m.getString("Content").contains("
")) { + String content = m.getString("Content").substring(m.getString("Content").indexOf("
") + 5); + m.put("Content", content); + m.put("groupMsg", true); + } + } else { + CommonTool.msgFormatter(m, "Content"); + } + if (m.getInteger("MsgType") == MsgType.MSGTYPE_TEXT) { // words 文本消息 + if (m.getString("Url").length() != 0) { + String regEx = "(.+?\\(.+?\\))"; + Matcher matcher = CommonTool.getMatcher(regEx, m.getString("Content")); + String data = "Map"; + if (matcher.find()) { + data = matcher.group(1); + } + msg.put("Type", "Map"); + msg.put("Text", data); + } else { + msg.put("Type", MsgType.TEXT); + msg.put("Text", m.getString("Content")); + } + m.put("Type", msg.getString("Type")); + m.put("Text", msg.getString("Text")); + } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_IMAGE + || m.getInteger("MsgType") == MsgType.MSGTYPE_EMOTICON) { // 图片消息 + m.put("Type", MsgType.PIC); + } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_VOICE) { // 语音消息 + m.put("Type", MsgType.VOICE); + } else if (m.getInteger("MsgType") == 37) {// friends 好友确认消息 + + } else if (m.getInteger("MsgType") == 42) { // 共享名片 + m.put("Type", MsgType.NAMECARD); + + } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_VIDEO + || m.getInteger("MsgType") == MsgType.MSGTYPE_MICROVIDEO) {// viedo + m.put("Type", MsgType.VIEDO); + } else if (m.getInteger("MsgType") == 49) { // sharing 分享链接 + + } else if (m.getInteger("MsgType") == 51) {// phone init 微信初始化消息 + + } else if (m.getInteger("MsgType") == 10000) {// 系统消息 + + } else if (m.getInteger("MsgType") == 10002) { // 撤回消息 + + } else { + LOG.info("Useless msg"); + } + result.add(m); + } + return result; + } + +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/Config.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/Config.java index d5a1694..c64472b 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/Config.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/Config.java @@ -5,6 +5,8 @@ import java.util.ArrayList; import java.util.Arrays; +import cn.zhouyafeng.itchat4j.utils.enums.OsNameEnum; + /** * 配置信息 * @@ -14,6 +16,9 @@ * */ public class Config { + + public static final String API_WXAPPID = "API_WXAPPID"; + public static final String picDir = "D://itchat4j"; public static final String VERSION = "1.2.18"; public static final String BASE_URL = "https://login.weixin.qq.com"; @@ -52,18 +57,18 @@ public static String getLocalPath() { * @author https://github.com/yaphone * @date 2017年4月8日 下午10:27:53 */ - public static OsName getOsName() { + public static OsNameEnum getOsNameEnum() { String os = System.getProperty("os.name").toUpperCase(); - if (os.indexOf(OsName.DARWIN.toString()) >= 0) { - return OsName.DARWIN; - } else if (os.indexOf(OsName.WINDOWS.toString()) >= 0) { - return OsName.WINDOWS; - } else if (os.indexOf(OsName.LINUX.toString()) >= 0) { - return OsName.LINUX; - } else if (os.indexOf(OsName.MAC.toString()) >= 0) { - return OsName.MAC; + if (os.indexOf(OsNameEnum.DARWIN.toString()) >= 0) { + return OsNameEnum.DARWIN; + } else if (os.indexOf(OsNameEnum.WINDOWS.toString()) >= 0) { + return OsNameEnum.WINDOWS; + } else if (os.indexOf(OsNameEnum.LINUX.toString()) >= 0) { + return OsNameEnum.LINUX; + } else if (os.indexOf(OsNameEnum.MAC.toString()) >= 0) { + return OsNameEnum.MAC; } - return OsName.OTHER; + return OsNameEnum.OTHER; } } diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/Constant.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/Constant.java deleted file mode 100644 index 9070cc4..0000000 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/Constant.java +++ /dev/null @@ -1,6 +0,0 @@ -package cn.zhouyafeng.itchat4j.utils; - -public class Constant { - public static final String API_WXAPPID = "API_WXAPPID"; - -} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/Contact.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/Contact.java deleted file mode 100644 index 9a7cbf8..0000000 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/Contact.java +++ /dev/null @@ -1,89 +0,0 @@ -package cn.zhouyafeng.itchat4j.utils; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.util.EntityUtils; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; - -public class Contact { - Logger logger = Logger.getLogger("Contact"); - Core core = Core.getInstance(); - CloseableHttpClient httpClient = MyHttpClient.getHttpClient(); - - public List getContact(boolean update) { - String url = String.format("%s/webwxgetcontact?r=%s&seq=0&skey=%s", core.loginInfo.get("url"), - String.valueOf(new Date().getTime()), core.loginInfo.get("skey")); - HttpGet httpGet = new HttpGet(url); - httpGet.setHeader("ContentType", "application/json; charset=UTF-8"); - httpGet.setHeader("User-Agent", Config.USER_AGENT); - try { - CloseableHttpResponse response = httpClient.execute(httpGet); - HttpEntity entity = response.getEntity(); - if (entity != null) { - String text = EntityUtils.toString(entity, "UTF-8"); - JSONObject obj = JSON.parseObject(text); - JSONArray tmpList = obj.getJSONArray("MemberList"); - List chatroomList = new ArrayList(); - List otherList = new ArrayList(); - for (int i = 0; i < tmpList.size(); i++) { - JSONObject m = tmpList.getJSONObject(i); - if (m.containsKey("Sex")) { - otherList.add(m); - } else { - JSONObject tmpObj = m.getJSONObject("UserName"); - if (tmpObj.toJSONString().contains("@@")) { - chatroomList.add(m); - } else if (tmpObj.toJSONString().contains("@")) { - otherList.add(m); - } - } - } - if (chatroomList.size() > 0) { - updateLocalChatrooms(chatroomList); - } - if (otherList.size() > 0) { - updateLocalFriends(otherList); - } - } - } catch (Exception e) { - logger.info(e.getMessage()); - } - return null; - - } - - Map updateLocalChatrooms(List chatrooms) { - for (JSONObject chatroom : chatrooms) { - // TODO utils.emoji_formatter(chatroom, 'NickName') - // TODO - } - - return null; - } - - void updateLocalFriends(List list) { - List fullList = new ArrayList(); - fullList.addAll(list); - fullList.addAll(core.getMemberList()); - for (int i = 0; i < fullList.size(); i++) { - JSONObject friend = fullList.get(i); - // TODO - // if 'NickName' in friend: - // utils.emoji_formatter(friend, 'NickName') - // if 'DisplayName' in friend: - // utils.emoji_formatter(friend, 'DisplayName') - core.getMemberList().add(friend); - } - } -} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java index e0a0c03..277ecb2 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java @@ -33,33 +33,26 @@ public static Core getInstance() { } boolean alive = false; - Storage storageClass = Storage.getInstance(); private int memberCount = 0; - private List userSelfList = storageClass.getUserSelfList(); - private List memberList = storageClass.getMemberList(); - private List contactList = storageClass.getContactList(); - private List groupList = storageClass.getGroupList(); - private List groupMemeberList = storageClass.getGroupList(); - private List publicUsersList = storageClass.getPublicUsersList(); - private List specialUsersList = storageClass.getSpecialUsersList(); - private List msgList = storageClass.getMsgList(); + private String userName; + private String nickName; + private List msgList = new ArrayList(); - private List groupIdList = new ArrayList(); // 群聊,以String格式保存群的userName,如@@37da24fee2114e9475729b942d130190ffddb669411228651da3e8a8933603c8 + private JSONObject userSelf; // 登陆账号自身信息 + private List memberList = new ArrayList(); // 好友+群聊+公众号+特殊账号 + private List contactList = new ArrayList();;// 好友 + private List groupList = new ArrayList();; // 群 + private List groupMemeberList = new ArrayList();; // 群聊成员字典 + private List publicUsersList = new ArrayList();;// 公众号/服务号 + private List specialUsersList = new ArrayList();;// 特殊账号 + private List groupIdList = new ArrayList(); Map loginInfo = new HashMap(); // CloseableHttpClient httpClient = HttpClients.createDefault(); MyHttpClient myHttpClient = MyHttpClient.getInstance(); String uuid = null; - Map functionDict = new HashMap() { - { - put("FriendChat", new HashMap()); - put("GroupChat", new HashMap()); - put("MpChat", new HashMap()); - } - }; - boolean useHotReload = false; String hotReloadDir = "itchat.pkl"; int receivingRetryCount = 5; @@ -72,14 +65,6 @@ public void setAlive(boolean alive) { this.alive = alive; } - public Storage getStorageClass() { - return storageClass; - } - - public void setStorageClass(Storage storageClass) { - this.storageClass = storageClass; - } - public List getMemberList() { return memberList; } @@ -104,10 +89,6 @@ public void setUuid(String uuid) { this.uuid = uuid; } - public Map getFunctionDict() { - return functionDict; - } - public int getMemberCount() { return memberCount; } @@ -116,10 +97,6 @@ public void setMemberCount(int memberCount) { this.memberCount = memberCount; } - public void setFunctionDict(Map functionDict) { - this.functionDict = functionDict; - } - public boolean isUseHotReload() { return useHotReload; } @@ -168,14 +145,6 @@ public void setGroupIdList(List groupIdList) { this.groupIdList = groupIdList; } - public List getUserSelfList() { - return userSelfList; - } - - public void setUserSelfList(List userSelfList) { - this.userSelfList = userSelfList; - } - public List getContactList() { return contactList; } @@ -216,4 +185,28 @@ public void setSpecialUsersList(List specialUsersList) { this.specialUsersList = specialUsersList; } + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public JSONObject getUserSelf() { + return userSelf; + } + + public void setUserSelf(JSONObject userSelf) { + this.userSelf = userSelf; + } + } diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/DownloadTools.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/DownloadTools.java deleted file mode 100644 index be1c73a..0000000 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/DownloadTools.java +++ /dev/null @@ -1,70 +0,0 @@ -package cn.zhouyafeng.itchat4j.utils; - -import java.io.FileOutputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -import org.apache.http.HttpEntity; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.util.EntityUtils; - -import com.alibaba.fastjson.JSONObject; - -/** - * 下载处理类 - * - * @author https://github.com/yaphone - * @date 创建时间:2017年4月21日 下午11:18:46 - * @version 1.0 - * - */ -public class DownloadTools { - private static Logger logger = Logger.getLogger("DownloadTools"); - private static Core core = Core.getInstance(); - private static MyHttpClient myHttpClient = core.getMyHttpClient(); - - /** - * 处理下载任务 - * - * @author https://github.com/yaphone - * @date 2017年4月21日 下午11:00:25 - * @param url - * @param msgId - * @param path - * @return - */ - public static Object getDownloadFn(JSONObject msg, String type, String path) { - Map headerMap = new HashMap(); - List params = new ArrayList(); - String url = ""; - if (type.equals(MsgType.PIC)) { - url = String.format("%s/webwxgetmsgimg", (String) core.getLoginInfo().get("url")); - } else if (type.equals(MsgType.VOICE)) { - url = String.format("%s/webwxgetvoice", (String) core.getLoginInfo().get("url")); - } else if (type.equals(MsgType.VIEDO)) { - headerMap.put("Range", "bytes=0-"); - url = String.format("%s/webwxgetvideo", (String) core.getLoginInfo().get("url")); - } - params.add(new BasicNameValuePair("msgid", msg.getString("NewMsgId"))); - params.add(new BasicNameValuePair("skey", (String) core.getLoginInfo().get("skey"))); - HttpEntity entity = myHttpClient.doGet(url, params, true, headerMap); - try { - OutputStream out = new FileOutputStream(path); - byte[] bytes = EntityUtils.toByteArray(entity); - out.write(bytes); - out.flush(); - out.close(); - // Tools.printQr(path); - - } catch (Exception e) { - logger.info(e.getMessage()); - return false; - } - return null; - }; - -} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/Storage.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/Storage.java deleted file mode 100644 index bf8950b..0000000 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/Storage.java +++ /dev/null @@ -1,136 +0,0 @@ -package cn.zhouyafeng.itchat4j.utils; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.fastjson.JSONObject; - -/** - * 存储登陆信息、好友列表等,全局只保存一份,单例模式 - * - * @author https://github.com/yaphone - * @date 创建时间:2017年4月23日 下午12:04:48 - * @version 1.0 - * - */ -public class Storage { - - private static Storage instance; - - private Storage() { - }; - - public static Storage getInstance() { - if (instance == null) { - synchronized (Storage.class) { - if (instance == null) { - instance = new Storage(); - } - } - } - return instance; - } - - private String userName; - private String nickName; - private List msgList = new ArrayList(); - - private List userSelfList = new ArrayList(); // 登陆账号自身信息 - private List memberList = new ArrayList(); // 好友+群聊+公众号+特殊账号 - private List contactList = new ArrayList();// 好友 - private List groupList = new ArrayList(); // 群 - private List groupMemeberList = new ArrayList(); // 群聊成员字典 - private List publicUsersList = new ArrayList();// 公众号/服务号 - private List specialUsersList = new ArrayList();// 特殊账号 - - private String lastInputUserName; - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getNickName() { - return nickName; - } - - public String getLastInputUserName() { - return lastInputUserName; - } - - public void setLastInputUserName(String lastInputUserName) { - this.lastInputUserName = lastInputUserName; - } - - public void setNickName(String nickName) { - this.nickName = nickName; - } - - public List getMemberList() { - return memberList; - } - - public void setMemberList(List memberList) { - this.memberList = memberList; - } - - public List getUserSelfList() { - return userSelfList; - } - - public void setUserSelfList(List userSelfList) { - this.userSelfList = userSelfList; - } - - public List getContactList() { - return contactList; - } - - public void setContactList(List contactList) { - this.contactList = contactList; - } - - public List getGroupList() { - return groupList; - } - - public void setGroupList(List groupList) { - this.groupList = groupList; - } - - public List getGroupMemeberList() { - return groupMemeberList; - } - - public void setGroupMemeberList(List groupMemeberList) { - this.groupMemeberList = groupMemeberList; - } - - public List getPublicUsersList() { - return publicUsersList; - } - - public void setPublicUsersList(List publicUsersList) { - this.publicUsersList = publicUsersList; - } - - public List getSpecialUsersList() { - return specialUsersList; - } - - public void setSpecialUsersList(List specialUsersList) { - this.specialUsersList = specialUsersList; - } - - public List getMsgList() { - return msgList; - } - - public void setMsgList(List msgList) { - this.msgList = msgList; - } - -} \ No newline at end of file diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/OsName.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/OsNameEnum.java similarity index 72% rename from src/main/java/cn/zhouyafeng/itchat4j/utils/OsName.java rename to src/main/java/cn/zhouyafeng/itchat4j/utils/enums/OsNameEnum.java index 643e86b..cfcd4ab 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/OsName.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/OsNameEnum.java @@ -1,4 +1,4 @@ -package cn.zhouyafeng.itchat4j.utils; +package cn.zhouyafeng.itchat4j.utils.enums; /** * 系统平台 @@ -8,6 +8,6 @@ * @version 1.0 * */ -public enum OsName { +public enum OsNameEnum { WINDOWS, LINUX, DARWIN, MAC, OTHER } diff --git a/src/main/java/cn/zhouyafeng/itchat4j/tools/CommonTool.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/CommonTool.java similarity index 94% rename from src/main/java/cn/zhouyafeng/itchat4j/tools/CommonTool.java rename to src/main/java/cn/zhouyafeng/itchat4j/utils/tools/CommonTool.java index 8101a3a..698e506 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/tools/CommonTool.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/CommonTool.java @@ -1,4 +1,4 @@ -package cn.zhouyafeng.itchat4j.tools; +package cn.zhouyafeng.itchat4j.utils.tools; import java.io.StringReader; import java.util.ArrayList; @@ -21,7 +21,7 @@ import com.vdurmont.emoji.EmojiParser; import cn.zhouyafeng.itchat4j.utils.Config; -import cn.zhouyafeng.itchat4j.utils.OsName; +import cn.zhouyafeng.itchat4j.utils.enums.OsNameEnum; /** * 常用工具类 @@ -35,9 +35,9 @@ public class CommonTool { public static boolean printQr(String qrPath) { - switch (Config.getOsName()) { + switch (Config.getOsNameEnum()) { case WINDOWS: - if (Config.getOsName().equals(OsName.WINDOWS)) { + if (Config.getOsNameEnum().equals(OsNameEnum.WINDOWS)) { Runtime runtime = Runtime.getRuntime(); try { runtime.exec("cmd /c start " + qrPath); @@ -47,7 +47,7 @@ public static boolean printQr(String qrPath) { } break; case MAC: - if (Config.getOsName().equals(OsName.MAC)) { + if (Config.getOsNameEnum().equals(OsNameEnum.MAC)) { Runtime runtime = Runtime.getRuntime(); try { runtime.exec("open " + qrPath); @@ -64,9 +64,9 @@ public static boolean printQr(String qrPath) { } public static boolean clearScreen() { - switch (Config.getOsName()) { + switch (Config.getOsNameEnum()) { case WINDOWS: - if (Config.getOsName().equals(OsName.WINDOWS)) { + if (Config.getOsNameEnum().equals(OsNameEnum.WINDOWS)) { Runtime runtime = Runtime.getRuntime(); try { runtime.exec("cmd /c " + "cls"); diff --git a/src/main/java/cn/zhouyafeng/itchat4j/tools/DownloadTools.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/DownloadTools.java similarity index 98% rename from src/main/java/cn/zhouyafeng/itchat4j/tools/DownloadTools.java rename to src/main/java/cn/zhouyafeng/itchat4j/utils/tools/DownloadTools.java index 44da9e7..7127d9f 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/tools/DownloadTools.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/DownloadTools.java @@ -1,4 +1,4 @@ -package cn.zhouyafeng.itchat4j.tools; +package cn.zhouyafeng.itchat4j.utils.tools; import java.io.FileOutputStream; import java.io.OutputStream; diff --git a/src/main/java/log4j.properties b/src/main/resources/log4j.properties similarity index 100% rename from src/main/java/log4j.properties rename to src/main/resources/log4j.properties diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java index 5196a5a..beb7f75 100644 --- a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java @@ -10,8 +10,8 @@ import cn.zhouyafeng.itchat4j.Wechat; import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; -import cn.zhouyafeng.itchat4j.utils.DownloadTools; import cn.zhouyafeng.itchat4j.utils.MsgType; +import cn.zhouyafeng.itchat4j.utils.tools.DownloadTools; /** * 简单示例程序,收到文本信息自动回复原信息,收到图片、语音、小视频后根据路径自动保存 diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java index 46a8b05..d69f6b5 100644 --- a/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java @@ -15,9 +15,9 @@ import cn.zhouyafeng.itchat4j.Wechat; import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; import cn.zhouyafeng.itchat4j.utils.Core; -import cn.zhouyafeng.itchat4j.utils.DownloadTools; import cn.zhouyafeng.itchat4j.utils.MsgType; import cn.zhouyafeng.itchat4j.utils.MyHttpClient; +import cn.zhouyafeng.itchat4j.utils.tools.DownloadTools; /** * 图灵机器人示例 From 09f96cf0665289dde6e425db76020dbc51d49bd3 Mon Sep 17 00:00:00 2001 From: yaphone Date: Sat, 13 May 2017 00:43:56 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=8C=85=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/zhouyafeng/itchat4j/Wechat.java | 6 +- .../itchat4j/service/ILoginService.java | 67 +++ .../service/impl/LoginServiceImpl.java | 531 ++++++++++++++++++ 3 files changed, 602 insertions(+), 2 deletions(-) create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/service/ILoginService.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java diff --git a/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java b/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java index 09848e4..be8e83d 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java @@ -6,8 +6,9 @@ import com.alibaba.fastjson.JSONObject; import cn.zhouyafeng.itchat4j.api.MessageTools; -import cn.zhouyafeng.itchat4j.components.Login; import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; +import cn.zhouyafeng.itchat4j.service.ILoginService; +import cn.zhouyafeng.itchat4j.service.impl.LoginServiceImpl; import cn.zhouyafeng.itchat4j.utils.Core; import cn.zhouyafeng.itchat4j.utils.MsgType; @@ -29,7 +30,8 @@ public Wechat(IMsgHandlerFace msgHandler, String qrPath) { System.setProperty("jsse.enableSNIExtension", "false"); // 防止SSL错误 this.msgHandler = msgHandler; - Login login = new Login(); + // Login login = new Login(); + ILoginService login = new LoginServiceImpl(); login.login(qrPath); }; diff --git a/src/main/java/cn/zhouyafeng/itchat4j/service/ILoginService.java b/src/main/java/cn/zhouyafeng/itchat4j/service/ILoginService.java new file mode 100644 index 0000000..1227f1c --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/service/ILoginService.java @@ -0,0 +1,67 @@ +package cn.zhouyafeng.itchat4j.service; + +/** + * 登陆服务接口 + * + * @author https://github.com/yaphone + * @date 创建时间:2017年5月13日 上午12:07:21 + * @version 1.0 + * + */ +public interface ILoginService { + + /** + * 登陆 + * + * @author https://github.com/yaphone + * @date 2017年5月13日 上午12:14:07 + * @return + */ + boolean login(String qrPath); + + /** + * 获取UUID + * + * @author https://github.com/yaphone + * @date 2017年5月13日 上午12:21:40 + * @param qrPath + * @return + */ + String getUuid(); + + /** + * 获取二维码图片 + * + * @author https://github.com/yaphone + * @date 2017年5月13日 上午12:13:51 + * @param qrPath + * @return + */ + boolean getQR(String qrPath); + + /** + * web初始化 + * + * @author https://github.com/yaphone + * @date 2017年5月13日 上午12:14:13 + * @return + */ + boolean webWxInit(); + + /** + * 微信状态通知 + * + * @author https://github.com/yaphone + * @date 2017年5月13日 上午12:14:24 + */ + void wxStatusNotify(); + + /** + * 接收消息 + * + * @author https://github.com/yaphone + * @date 2017年5月13日 上午12:14:37 + */ + void startReceiving(); + +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java b/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java new file mode 100644 index 0000000..ef352ee --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java @@ -0,0 +1,531 @@ +package cn.zhouyafeng.itchat4j.service.impl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; +import java.util.regex.Matcher; + +import org.apache.http.HttpEntity; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import cn.zhouyafeng.itchat4j.core.MsgCenter; +import cn.zhouyafeng.itchat4j.service.ILoginService; +import cn.zhouyafeng.itchat4j.utils.Config; +import cn.zhouyafeng.itchat4j.utils.Core; +import cn.zhouyafeng.itchat4j.utils.MyHttpClient; +import cn.zhouyafeng.itchat4j.utils.tools.CommonTool; + +/** + * 登陆服务实现类 + * + * @author https://github.com/yaphone + * @date 创建时间:2017年5月13日 上午12:09:35 + * @version 1.0 + * + */ +public class LoginServiceImpl implements ILoginService { + private static Logger LOG = LoggerFactory.getLogger(LoginServiceImpl.class); + private String baseUrl = Config.BASE_URL; + private boolean isLOGinIn = false; + + private Core core = Core.getInstance(); + + private MyHttpClient myHttpClient = core.getMyHttpClient(); + + public LoginServiceImpl() { + + } + + @Override + public boolean login(String qrPath) { + if (core.isAlive()) { // 已登陆 + LOG.info("itchat has already LOGged in."); + return true; + } + while (true) { + for (int count = 0; count < 10; count++) { + LOG.info("Getting uuid of QR code."); + while (getUuid() == null) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + LOG.info(e.getMessage()); + } + } + LOG.info("Downloading QR code."); + Boolean qrStarge = getQR(qrPath); + if (qrStarge) { // 获取登陆二维码图片成功 + LOG.info("Get QR success"); + break; + } else if (count == 10) { + LOG.info("Failed to get QR code, please restart the program."); + System.exit(0); + } + } + LOG.info("Please scan the QR code to LOG in."); + while (!isLOGinIn) { + String status = checkLogin(); + if (status.equals("200")) { + isLOGinIn = true; + LOG.info(("登陆成功")); + } else if (status.equals("201")) { + LOG.info("Please press confirm on your phone."); + isLOGinIn = false; + } else { + break; + } + } + if (isLOGinIn) + break; + LOG.info("LOG in time out, reloading QR code"); + } + this.webWxInit(); + this.wxStatusNotify(); + CommonTool.clearScreen(); + LOG.info(String.format("LOGin successfully as %s", core.getNickName())); + startReceiving(); + return true; + } + + @Override + public String getUuid() { + String result = null; + String uuidUrl = baseUrl + "/jslogin"; + List params = new ArrayList(); + params.add(new BasicNameValuePair("appid", "wx782c26e4c19acffb")); + params.add(new BasicNameValuePair("fun", "new")); + HttpEntity entity = myHttpClient.doGet(uuidUrl, params, true, null); + try { + result = EntityUtils.toString(entity); + } catch (Exception e) { + LOG.info(e.getMessage()); + } + String regEx = "window.QRLogin.code = (\\d+); window.QRLogin.uuid = \"(\\S+?)\";"; + Matcher matcher = CommonTool.getMatcher(regEx, result); + if (matcher.find()) { + if ((matcher.group(1).equals("200"))) { + core.setUuid(matcher.group(2));// + } + } + return core.getUuid(); + } + + @Override + public boolean getQR(String qrPath) { + qrPath = qrPath + File.separator + "QR.jpg"; + String qrUrl = baseUrl + "/qrcode/" + core.getUuid(); + HttpEntity entity = myHttpClient.doGet(qrUrl, null, true, null); + try { + OutputStream out = new FileOutputStream(qrPath); + byte[] bytes = EntityUtils.toByteArray(entity); + out.write(bytes); + out.flush(); + out.close(); + try { + CommonTool.printQr(qrPath); // 打开登陆二维码图片 + } catch (Exception e) { + LOG.info(e.getMessage()); + } + + } catch (Exception e) { + LOG.info(e.getMessage()); + return false; + } + + return true; + } + + @Override + public boolean webWxInit() { + JSONObject obj = null; + String url = core.getLoginInfo().get("url") + "/webwxinit?&r=" + String.valueOf(new Date().getTime()); + @SuppressWarnings("unchecked") + Map> paramMap = (Map>) core.getLoginInfo() + .get("baseRequest"); + String paramStr = JSON.toJSONString(paramMap); + try { + HttpEntity entity = myHttpClient.doPost(url, paramStr); + String result = EntityUtils.toString(entity, "UTF-8"); + obj = JSON.parseObject(result); + // TODO utils.emoji_formatter(dic['User'], 'NickName') + core.getLoginInfo().put("InviteStartCount", obj.getInteger("InviteStartCount")); + core.getLoginInfo().put("User", CommonTool.structFriendInfo(obj.getJSONObject("User"))); // 为userObj添加新字段 + core.getLoginInfo().put("SyncKey", obj.getJSONObject("SyncKey")); + JSONArray syncArray = obj.getJSONObject("SyncKey").getJSONArray("List"); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < syncArray.size(); i++) { + sb.append(syncArray.getJSONObject(i).getString("Key") + "_" + + syncArray.getJSONObject(i).getString("Val") + "|"); + } + String synckey = sb.toString(); + core.getLoginInfo().put("synckey", synckey.substring(0, synckey.length() - 1));// 1_656161336|2_656161626|3_656161313|11_656159955|13_656120033|201_1492273724|1000_1492265953|1001_1492250432|1004_1491805192 + core.setUserName((obj.getJSONObject("User")).getString("UserName")); + core.setNickName((obj.getJSONObject("User")).getString("NickName")); + core.setUserSelf(obj.getJSONObject("User")); + } catch (Exception e) { + e.printStackTrace(); + } + return true; + } + + @Override + public void wxStatusNotify() { + String url = (String) core.getLoginInfo().get("url"); + String passTicket = (String) core.getLoginInfo().get("pass_ticket"); + String mobileUrl = String.format("%s/webwxstatusnotify?lang=zh_CN&pass_ticket=%s", url, passTicket); + Map paramMap = new HashMap(); + @SuppressWarnings("unchecked") + Map> baseRequestMap = (Map>) core.getLoginInfo() + .get("baseRequest"); + paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest")); + paramMap.put("Code", 3); + paramMap.put("FromUserName", core.getUserName()); + paramMap.put("ToUserName", core.getUserName()); + paramMap.put("ClientMsgId", String.valueOf(new Date().getTime())); + String paramStr = JSON.toJSONString(paramMap); + try { + HttpEntity entity = myHttpClient.doPost(mobileUrl, paramStr); + EntityUtils.toString(entity, "UTF-8"); + } catch (Exception e) { + + } + + } + + @Override + public void startReceiving() { + core.setAlive(true); + new Thread(new Runnable() { + int retryCount = 0; + + @Override + public void run() { + while (core.isAlive()) { + try { + Map resultMap = syncCheck(); + String retcode = resultMap.get("retcode"); + String selector = resultMap.get("selector"); + if (retcode.equals("9999")) { + continue; + } else if (retcode.equals("1100")) { // 退出 + LOG.info("login out"); + break; + } else if (retcode.equals("1101")) { // 其它地方登陆 + LOG.info("login otherwhere"); + break; + } else if (retcode.equals("1102")) { // 移动端退出 + LOG.info("login quit on phone"); + break; + } else if (retcode.equals("0")) { + if (selector.equals("2")) { + JSONObject msgObj = webWxSync(); + if (msgObj != null) { + try { + JSONArray msgList = new JSONArray(); + msgList = msgObj.getJSONArray("AddMsgList"); + msgList = MsgCenter.produceMsg(msgList); + for (int j = 0; j < msgList.size(); j++) { + core.getMsgList().add(msgList.getJSONObject(j)); + } + } catch (Exception e) { + LOG.info(e.getMessage()); + } + } else if (selector.equals("7")) { + webWxSync(); + } else if (selector.equals("4")) { + // 保存群聊到通讯录 + // 修改群名称 + // 新增或删除联系人 + // 群聊成员数目变化 + // TODO + } else if (selector.equals("3") || selector.equals("6")) { + break; + } + } + } else { + JSONObject obj = webWxSync(); + LOG.info(obj.toJSONString()); + } + } catch (Exception e) { + LOG.info(e.getMessage()); + retryCount += 1; + if (core.getReceivingRetryCount() < retryCount) { + core.setAlive(false); + } else { + try { + Thread.sleep(1000); + } catch (InterruptedException e1) { + LOG.info(e.getMessage()); + } + } + } + + } + } + }).start(); + + } + + /** + * 检查登陆状态 + * + * @author https://github.com/yaphone + * @date 2017年4月8日 下午11:22:16 + * @return + */ + public String checkLogin() { + String result = ""; + String checkUrl = baseUrl + "/cgi-bin/mmwebwx-bin/login"; + Long localTime = new Date().getTime(); + List params = new ArrayList(); + params.add(new BasicNameValuePair("loginicon", "true")); + params.add(new BasicNameValuePair("uuid", core.getUuid())); + params.add(new BasicNameValuePair("tip", "0")); + params.add(new BasicNameValuePair("r", String.valueOf(localTime / 1579L))); + params.add(new BasicNameValuePair("_", String.valueOf(localTime))); + HttpEntity entity = myHttpClient.doGet(checkUrl, params, true, null); + try { + result = EntityUtils.toString(entity); + } catch (Exception e) { + LOG.info(e.getMessage()); + } + String regEx = "window.code=(\\d+)"; + Matcher matcher = CommonTool.getMatcher(regEx, result); + if (matcher.find()) { + if (matcher.group(1).equals("200")) { // 已登陆 + processLoginInfo(result); + return "200"; + } else if (matcher.group(1).equals("201")) { // 已扫描,未登陆 + return "201"; + } + } + return "400"; + } + + /** + * 处理登陆信息 + * + * @author https://github.com/yaphone + * @date 2017年4月9日 下午12:16:26 + * @param result + */ + private void processLoginInfo(String loginContent) { + String regEx = "window.redirect_uri=\"(\\S+)\";"; + Matcher matcher = CommonTool.getMatcher(regEx, loginContent); + if (matcher.find()) { + String originalUrl = matcher.group(1); + String url = originalUrl.substring(0, originalUrl.lastIndexOf('/')); // https://wx2.qq.com/cgi-bin/mmwebwx-bin + core.getLoginInfo().put("url", url); + Map> possibleUrlMap = getPossibleUrlMap(); + Iterator>> iterator = possibleUrlMap.entrySet().iterator(); + Map.Entry> entry; + String fileUrl; + String syncUrl; + while (iterator.hasNext()) { + entry = iterator.next(); + String indexUrl = entry.getKey(); + fileUrl = "https://" + entry.getValue().get(0) + "/cgi-bin/mmwebwx-bin"; + syncUrl = "https://" + entry.getValue().get(1) + "/cgi-bin/mmwebwx-bin"; + if (core.getLoginInfo().get("url").toString().contains(indexUrl)) { + core.getLoginInfo().put("fileUrl", fileUrl); + core.getLoginInfo().put("syncUrl", syncUrl); + break; + } + } + if (core.getLoginInfo().get("fileUrl") == null && core.getLoginInfo().get("syncUrl") == null) { + core.getLoginInfo().put("fileUrl", url); + core.getLoginInfo().put("syncUrl", url); + } + core.getLoginInfo().put("deviceid", "e" + String.valueOf(new Random().nextLong()).substring(1, 16)); // 生成15位随机数 + core.getLoginInfo().put("BaseRequest", new ArrayList()); + String text = ""; + // // 禁止重定向 + + try { + HttpEntity entity = myHttpClient.doGet(originalUrl, null, false, null); + text = EntityUtils.toString(entity); + } catch (Exception e) { + LOG.info(e.getMessage()); + return; + } + Document doc = CommonTool.xmlParser(text); + Map> BaseRequest = new HashMap>(); + Map baseRequest = new HashMap(); + if (doc != null) { + core.getLoginInfo().put("skey", + doc.getElementsByTagName("skey").item(0).getFirstChild().getNodeValue()); + baseRequest.put("Skey", (String) core.getLoginInfo().get("skey")); + core.getLoginInfo().put("wxsid", + doc.getElementsByTagName("wxsid").item(0).getFirstChild().getNodeValue()); + baseRequest.put("Sid", (String) core.getLoginInfo().get("wxsid")); + core.getLoginInfo().put("wxuin", + doc.getElementsByTagName("wxuin").item(0).getFirstChild().getNodeValue()); + baseRequest.put("Uin", (String) core.getLoginInfo().get("wxuin")); + core.getLoginInfo().put("pass_ticket", + doc.getElementsByTagName("pass_ticket").item(0).getFirstChild().getNodeValue()); + baseRequest.put("DeviceID", (String) core.getLoginInfo().get("deviceid")); + BaseRequest.put("BaseRequest", baseRequest); + core.getLoginInfo().put("baseRequest", BaseRequest); + } + + } + } + + private Map> getPossibleUrlMap() { + Map> possibleUrlMap = new HashMap>(); + possibleUrlMap.put("wx2.qq.com", new ArrayList() { + /** + * + */ + private static final long serialVersionUID = 1L; + + { + add("file.wx2.qq.com"); + add("webpush.wx2.qq.com"); + } + }); + possibleUrlMap.put("wx8.qq.com", new ArrayList() { + /** + * + */ + private static final long serialVersionUID = 1L; + + { + add("file.wx8.qq.com"); + add("webpush.wx8.qq.com"); + } + }); + + possibleUrlMap.put("web2.wechat.com", new ArrayList() { + /** + * + */ + private static final long serialVersionUID = 1L; + + { + add("file.web2.wechat.com"); + add("webpush.web2.wechat.com"); + } + }); + possibleUrlMap.put("wechat.com", new ArrayList() { + /** + * + */ + private static final long serialVersionUID = 1L; + + { + add("file.web.wechat.com"); + add("webpush.web.wechat.com"); + } + }); + return possibleUrlMap; + } + + /** + * 同步消息 sync the messages + * + * @author https://github.com/yaphone + * @date 2017年5月12日 上午12:24:55 + * @return + */ + private JSONObject webWxSync() { + JSONObject result = null; + String url = String.format("%s/webwxsync?sid=%s&skey=%s&pass_ticket=%s", core.getLoginInfo().get("url"), + core.getLoginInfo().get("wxsid"), core.getLoginInfo().get("skey"), + core.getLoginInfo().get("pass_ticket")); + Map paramMap = new HashMap(); + @SuppressWarnings("unchecked") + Map> baseRequestMap = (Map>) core.getLoginInfo() + .get("baseRequest"); + paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest")); + paramMap.put("SyncKey", core.getLoginInfo().get("SyncKey")); + paramMap.put("rr", -new Date().getTime() / 1000); + String paramStr = JSON.toJSONString(paramMap); + try { + HttpEntity entity = myHttpClient.doPost(url, paramStr); + String text = EntityUtils.toString(entity, "UTF-8"); + JSONObject obj = JSON.parseObject(text); + if (obj.getJSONObject("BaseResponse").getInteger("Ret") != 0) { + result = null; + } else { + result = obj; + core.getLoginInfo().put("SyncKey", obj.getJSONObject("SyncCheckKey")); + JSONArray syncArray = obj.getJSONObject("SyncKey").getJSONArray("List"); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < syncArray.size(); i++) { + sb.append(syncArray.getJSONObject(i).getString("Key") + "_" + + syncArray.getJSONObject(i).getString("Val") + "|"); + } + String synckey = sb.toString(); + core.getLoginInfo().put("synckey", synckey.substring(0, synckey.length() - 1));// 1_656161336|2_656161626|3_656161313|11_656159955|13_656120033|201_1492273724|1000_1492265953|1001_1492250432|1004_1491805192 + } + } catch (Exception e) { + LOG.info(e.getMessage()); + } + return result; + + } + + /** + * 检查是否有新消息 check whether there's a message + * + * @author https://github.com/yaphone + * @date 2017年4月16日 上午11:11:34 + * @return + * + */ + private Map syncCheck() { + Map resultMap = new HashMap(); + String syncUrl = (String) core.getLoginInfo().get("syncUrl"); + // String syncUrl = "https://webpush.wx2.qq.com/cgi-bin/mmwebwx-bin"; + if (syncUrl == null || syncUrl.equals("")) { + syncUrl = (String) core.getLoginInfo().get("url"); + } + String url = String.format("%s/synccheck", syncUrl); + List params = new ArrayList(); + params.add(new BasicNameValuePair("r", String.valueOf(new Date().getTime()))); + params.add(new BasicNameValuePair("skey", (String) core.getLoginInfo().get("skey"))); + params.add(new BasicNameValuePair("sid", (String) core.getLoginInfo().get("wxsid"))); + params.add(new BasicNameValuePair("uin", (String) core.getLoginInfo().get("wxuin"))); + params.add(new BasicNameValuePair("deviceid", (String) core.getLoginInfo().get("deviceid"))); + params.add(new BasicNameValuePair("synckey", (String) core.getLoginInfo().get("synckey"))); + params.add(new BasicNameValuePair("_", String.valueOf(new Date().getTime()))); + try { + HttpEntity entity = myHttpClient.doGet(url, params, true, null); + if (entity == null) { + resultMap.put("retcode", "9999"); + resultMap.put("selector", "9999"); + return resultMap; + } + String text = EntityUtils.toString(entity); + String regEx = "window.synccheck=\\{retcode:\"(\\d+)\",selector:\"(\\d+)\"\\}"; + Matcher matcher = CommonTool.getMatcher(regEx, text); + if (!matcher.find() || matcher.group(1).equals("2")) { + LOG.info(String.format("Unexpected sync check result: %s", text)); + } else { + resultMap.put("retcode", matcher.group(1)); + resultMap.put("selector", matcher.group(2)); + } + } catch (Exception e) { + e.printStackTrace(); + } + return resultMap; + } + +} From a2edcbc9610d1f5d2922e1672d9bd72079e59d2a Mon Sep 17 00:00:00 2001 From: yaphone Date: Sat, 13 May 2017 22:03:59 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E7=BB=93=E6=9E=84=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/zhouyafeng/itchat4j/Wechat.java | 3 +- .../java/cn/zhouyafeng/itchat4j/Wechat2.java | 33 +++ .../itchat4j/controller/LoginController.java | 77 +++++ .../zhouyafeng/itchat4j/core/MsgCenter.java | 38 +++ .../itchat4j/service/ILoginService.java | 10 +- .../service/impl/LoginServiceImpl.java | 271 ++++++++++-------- .../cn/zhouyafeng/itchat4j/utils/Core.java | 17 ++ .../zhouyafeng/itchat4j/utils/SleepUtils.java | 20 ++ .../itchat4j/utils/enums/ResultEnum.java | 35 +++ .../utils/enums/StorageLoginInfoEnum.java | 59 ++++ .../itchat4j/utils/enums/URLEnum.java | 36 +++ .../utils/enums/parameters/BaseParaEnum.java | 36 +++ .../utils/enums/parameters/LoginParaEnum.java | 31 ++ .../parameters/StatusNotifyParaEnum.java | 30 ++ .../utils/enums/parameters/UUIDParaEnum.java | 30 ++ src/main/resources/log4j.properties | 17 +- .../zhouyafeng/itchat4j/demo/SimpleDemo.java | 4 +- .../itchat4j/demo/demo2/SimpleDemo2.java | 88 ++++++ 18 files changed, 697 insertions(+), 138 deletions(-) create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/Wechat2.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/controller/LoginController.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/SleepUtils.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/enums/ResultEnum.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/enums/StorageLoginInfoEnum.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/enums/URLEnum.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/BaseParaEnum.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/LoginParaEnum.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/StatusNotifyParaEnum.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/UUIDParaEnum.java create mode 100644 src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java diff --git a/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java b/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java index be8e83d..943826a 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java @@ -32,8 +32,7 @@ public Wechat(IMsgHandlerFace msgHandler, String qrPath) { this.msgHandler = msgHandler; // Login login = new Login(); ILoginService login = new LoginServiceImpl(); - login.login(qrPath); - + login.login(); }; public void start() { diff --git a/src/main/java/cn/zhouyafeng/itchat4j/Wechat2.java b/src/main/java/cn/zhouyafeng/itchat4j/Wechat2.java new file mode 100644 index 0000000..41dfd46 --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/Wechat2.java @@ -0,0 +1,33 @@ +package cn.zhouyafeng.itchat4j; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.zhouyafeng.itchat4j.controller.LoginController; +import cn.zhouyafeng.itchat4j.core.MsgCenter; +import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; + +public class Wechat2 { + private static final Logger LOG = LoggerFactory.getLogger(Wechat2.class); + private IMsgHandlerFace msgHandler; + + public Wechat2(IMsgHandlerFace msgHandler, String qrPath) { + System.setProperty("jsse.enableSNIExtension", "false"); // 防止SSL错误 + this.msgHandler = msgHandler; + + // 登陆 + LoginController login = new LoginController(); + login.login(qrPath); + } + + public void start() { + LOG.info("+++++++++++++++++++开始消息处理+++++++++++++++++++++"); + new Thread(new Runnable() { + @Override + public void run() { + MsgCenter.handleMsg(msgHandler); + } + }).start(); + } + +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/controller/LoginController.java b/src/main/java/cn/zhouyafeng/itchat4j/controller/LoginController.java new file mode 100644 index 0000000..60ab1df --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/controller/LoginController.java @@ -0,0 +1,77 @@ +package cn.zhouyafeng.itchat4j.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.zhouyafeng.itchat4j.service.ILoginService; +import cn.zhouyafeng.itchat4j.service.impl.LoginServiceImpl; +import cn.zhouyafeng.itchat4j.utils.Core; +import cn.zhouyafeng.itchat4j.utils.SleepUtils; +import cn.zhouyafeng.itchat4j.utils.tools.CommonTool; + +/** + * 登陆控制器 + * + * @author https://github.com/yaphone + * @date 创建时间:2017年5月13日 下午12:56:07 + * @version 1.0 + * + */ +public class LoginController { + private static Logger LOG = LoggerFactory.getLogger(LoginController.class); + private ILoginService loginService = new LoginServiceImpl(); + private static Core core = Core.getInstance(); + + public void login(String qrPath) { + if (core.isAlive()) { // 已登陆 + LOG.info("itchat4j已登陆"); + return; + } + while (true) { + for (int count = 0; count < 10; count++) { + LOG.info("获取UUID"); + while (loginService.getUuid() == null) { + LOG.info("1. 获取微信UUID"); + while (loginService.getUuid() == null) { + LOG.warn("1.1. 获取微信UUID失败,两秒后重新获取"); + SleepUtils.sleep(2000); + } + } + LOG.info("2. 获取登陆二维码图片"); + if (loginService.getQR(qrPath)) { + break; + } else if (count == 10) { + LOG.error("2.2. 获取登陆二维码图片失败,系统退出"); + System.exit(0); + } + } + LOG.info("3. 请扫描二维码图片,并在手机上确认"); + if (!core.isAlive()) { + loginService.login(); + core.setAlive(true); + LOG.info(("登陆成功")); + break; + } + LOG.info("4. 登陆超时,请重新扫描二维码图片"); + } + + LOG.info("5. 登陆成功,微信初始化"); + if (!loginService.webWxInit()) { + LOG.info("6. 微信初始化异常"); + System.exit(0); + } + + LOG.info("6. 开启微信状态通知"); + loginService.wxStatusNotify(); + + LOG.info("6. 清除。。。。"); + CommonTool.clearScreen(); + LOG.info(String.format("欢迎回来, %s", core.getNickName())); + + LOG.info("7. 开始接收消息"); + loginService.startReceiving(); + + LOG.info("8. 获取联系人信息"); + loginService.webWxGetContact(); + } +} \ No newline at end of file diff --git a/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java b/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java index 7c57738..aee2779 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java @@ -1,5 +1,6 @@ package cn.zhouyafeng.itchat4j.core; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import org.slf4j.Logger; @@ -8,6 +9,8 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import cn.zhouyafeng.itchat4j.api.MessageTools; +import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; import cn.zhouyafeng.itchat4j.utils.Core; import cn.zhouyafeng.itchat4j.utils.MsgType; import cn.zhouyafeng.itchat4j.utils.tools.CommonTool; @@ -95,4 +98,39 @@ public static JSONArray produceMsg(JSONArray msgList) { return result; } + public static void handleMsg(IMsgHandlerFace msgHandler) { + while (true) { + if (core.getMsgList().size() > 0 && core.getMsgList().get(0).getString("Content") != null) { + // System.out.println(core.getMsgList().get(0)); + if (core.getMsgList().get(0).getString("Content").length() > 0) { + JSONObject msg = core.getMsgList().get(0); + if (msg.getString("Type") != null) { + if (msg.getString("Type").equals(MsgType.TEXT)) { + String result = msgHandler.textMsgHandle(msg); + MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); + } else if (msg.getString("Type").equals(MsgType.PIC)) { + String result = msgHandler.picMsgHandle(msg); + MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); + } else if (msg.getString("Type").equals(MsgType.VOICE)) { + String result = msgHandler.voiceMsgHandle(msg); + MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); + } else if (msg.getString("Type").equals(MsgType.VIEDO)) { + String result = msgHandler.viedoMsgHandle(msg); + MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); + } else if (msg.getString("Type").equals(MsgType.NAMECARD)) { + String result = msgHandler.nameCardMsgHandle(msg); + MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); + } + } + } + core.getMsgList().remove(0); + } + try { + TimeUnit.MILLISECONDS.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } diff --git a/src/main/java/cn/zhouyafeng/itchat4j/service/ILoginService.java b/src/main/java/cn/zhouyafeng/itchat4j/service/ILoginService.java index 1227f1c..349ecf3 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/service/ILoginService.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/service/ILoginService.java @@ -17,7 +17,7 @@ public interface ILoginService { * @date 2017年5月13日 上午12:14:07 * @return */ - boolean login(String qrPath); + boolean login(); /** * 获取UUID @@ -64,4 +64,12 @@ public interface ILoginService { */ void startReceiving(); + /** + * 获取微信联系人 + * + * @author https://github.com/yaphone + * @date 2017年5月13日 下午2:26:18 + */ + void webWxGetContact(); + } diff --git a/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java b/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java index ef352ee..66513b6 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java @@ -29,6 +29,14 @@ import cn.zhouyafeng.itchat4j.utils.Config; import cn.zhouyafeng.itchat4j.utils.Core; import cn.zhouyafeng.itchat4j.utils.MyHttpClient; +import cn.zhouyafeng.itchat4j.utils.SleepUtils; +import cn.zhouyafeng.itchat4j.utils.enums.ResultEnum; +import cn.zhouyafeng.itchat4j.utils.enums.StorageLoginInfoEnum; +import cn.zhouyafeng.itchat4j.utils.enums.URLEnum; +import cn.zhouyafeng.itchat4j.utils.enums.parameters.BaseParaEnum; +import cn.zhouyafeng.itchat4j.utils.enums.parameters.LoginParaEnum; +import cn.zhouyafeng.itchat4j.utils.enums.parameters.StatusNotifyParaEnum; +import cn.zhouyafeng.itchat4j.utils.enums.parameters.UUIDParaEnum; import cn.zhouyafeng.itchat4j.utils.tools.CommonTool; /** @@ -42,9 +50,9 @@ public class LoginServiceImpl implements ILoginService { private static Logger LOG = LoggerFactory.getLogger(LoginServiceImpl.class); private String baseUrl = Config.BASE_URL; - private boolean isLOGinIn = false; private Core core = Core.getInstance(); + private MyHttpClient httpClient = core.getMyHttpClient(); private MyHttpClient myHttpClient = core.getMyHttpClient(); @@ -53,83 +61,77 @@ public LoginServiceImpl() { } @Override - public boolean login(String qrPath) { - if (core.isAlive()) { // 已登陆 - LOG.info("itchat has already LOGged in."); - return true; - } - while (true) { - for (int count = 0; count < 10; count++) { - LOG.info("Getting uuid of QR code."); - while (getUuid() == null) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - LOG.info(e.getMessage()); - } - } - LOG.info("Downloading QR code."); - Boolean qrStarge = getQR(qrPath); - if (qrStarge) { // 获取登陆二维码图片成功 - LOG.info("Get QR success"); - break; - } else if (count == 10) { - LOG.info("Failed to get QR code, please restart the program."); - System.exit(0); - } - } - LOG.info("Please scan the QR code to LOG in."); - while (!isLOGinIn) { - String status = checkLogin(); - if (status.equals("200")) { - isLOGinIn = true; + public boolean login() { + + boolean isLogin = false; + // 组装参数和URL + List params = new ArrayList(); + params.add(new BasicNameValuePair(LoginParaEnum.LOGIN_ICON.para(), LoginParaEnum.LOGIN_ICON.value())); + params.add(new BasicNameValuePair(LoginParaEnum.UUID.para(), core.getUuid())); + params.add(new BasicNameValuePair(LoginParaEnum.TIP.para(), LoginParaEnum.TIP.value())); + + // long time = 4000; + while (!isLogin) { + // SleepUtils.sleep(time += 1000); + long millis = System.currentTimeMillis(); + params.add(new BasicNameValuePair(LoginParaEnum.R.para(), String.valueOf(millis / 1579L))); + params.add(new BasicNameValuePair(LoginParaEnum._.para(), String.valueOf(millis))); + HttpEntity entity = httpClient.doGet(URLEnum.LOGIN_URL.getUrl(), params, true, null); + + try { + String result = EntityUtils.toString(entity); + String status = checklogin(result); + + if (ResultEnum.SUCCESS.getCode().equals(status)) { LOG.info(("登陆成功")); - } else if (status.equals("201")) { - LOG.info("Please press confirm on your phone."); - isLOGinIn = false; - } else { + processLoginInfo(result); // 处理结果 + isLogin = true; + core.setAlive(isLogin); break; } + + if (ResultEnum.WAIT_CONFIRM.getCode().equals(status)) { + LOG.info("请点击微信确认按钮,进行登陆"); + } + + } catch (Exception e) { + LOG.error("微信登陆异常!", e); } - if (isLOGinIn) - break; - LOG.info("LOG in time out, reloading QR code"); } - this.webWxInit(); - this.wxStatusNotify(); - CommonTool.clearScreen(); - LOG.info(String.format("LOGin successfully as %s", core.getNickName())); - startReceiving(); - return true; + return isLogin; } @Override public String getUuid() { - String result = null; - String uuidUrl = baseUrl + "/jslogin"; + // 组装参数和URL List params = new ArrayList(); - params.add(new BasicNameValuePair("appid", "wx782c26e4c19acffb")); - params.add(new BasicNameValuePair("fun", "new")); - HttpEntity entity = myHttpClient.doGet(uuidUrl, params, true, null); + params.add(new BasicNameValuePair(UUIDParaEnum.APP_ID.para(), UUIDParaEnum.APP_ID.value())); + params.add(new BasicNameValuePair(UUIDParaEnum.FUN.para(), UUIDParaEnum.FUN.value())); + params.add(new BasicNameValuePair(UUIDParaEnum.LANG.para(), UUIDParaEnum.LANG.value())); + params.add(new BasicNameValuePair(UUIDParaEnum._.para(), String.valueOf(System.currentTimeMillis()))); + + HttpEntity entity = httpClient.doGet(URLEnum.UUID_URL.getUrl(), params, true, null); + try { - result = EntityUtils.toString(entity); - } catch (Exception e) { - LOG.info(e.getMessage()); - } - String regEx = "window.QRLogin.code = (\\d+); window.QRLogin.uuid = \"(\\S+?)\";"; - Matcher matcher = CommonTool.getMatcher(regEx, result); - if (matcher.find()) { - if ((matcher.group(1).equals("200"))) { - core.setUuid(matcher.group(2));// + String result = EntityUtils.toString(entity); + String regEx = "window.QRLogin.code = (\\d+); window.QRLogin.uuid = \"(\\S+?)\";"; + Matcher matcher = CommonTool.getMatcher(regEx, result); + if (matcher.find()) { + if ((ResultEnum.SUCCESS.getCode().equals(matcher.group(1)))) { + core.setUuid(matcher.group(2)); + } } + } catch (Exception e) { + LOG.error(e.getMessage(), e); } + return core.getUuid(); } @Override public boolean getQR(String qrPath) { qrPath = qrPath + File.separator + "QR.jpg"; - String qrUrl = baseUrl + "/qrcode/" + core.getUuid(); + String qrUrl = URLEnum.QRCODE_URL.getUrl() + core.getUuid(); HttpEntity entity = myHttpClient.doGet(qrUrl, null, true, null); try { OutputStream out = new FileOutputStream(qrPath); @@ -153,57 +155,67 @@ public boolean getQR(String qrPath) { @Override public boolean webWxInit() { - JSONObject obj = null; - String url = core.getLoginInfo().get("url") + "/webwxinit?&r=" + String.valueOf(new Date().getTime()); - @SuppressWarnings("unchecked") - Map> paramMap = (Map>) core.getLoginInfo() - .get("baseRequest"); - String paramStr = JSON.toJSONString(paramMap); + // 组装请求URL和参数 + String url = String.format(URLEnum.INIT_URL.getUrl(), + core.getLoginInfo().get(StorageLoginInfoEnum.url.getKey()), + String.valueOf(System.currentTimeMillis() / 3158L), + core.getLoginInfo().get(StorageLoginInfoEnum.pass_ticket.getKey())); + + Map paramMap = core.getParamMap(); + + // 请求初始化接口 + HttpEntity entity = httpClient.doPost(url, JSON.toJSONString(paramMap)); try { - HttpEntity entity = myHttpClient.doPost(url, paramStr); String result = EntityUtils.toString(entity, "UTF-8"); - obj = JSON.parseObject(result); - // TODO utils.emoji_formatter(dic['User'], 'NickName') - core.getLoginInfo().put("InviteStartCount", obj.getInteger("InviteStartCount")); - core.getLoginInfo().put("User", CommonTool.structFriendInfo(obj.getJSONObject("User"))); // 为userObj添加新字段 - core.getLoginInfo().put("SyncKey", obj.getJSONObject("SyncKey")); - JSONArray syncArray = obj.getJSONObject("SyncKey").getJSONArray("List"); + JSONObject obj = JSON.parseObject(result); + + LOG.info(obj.toString());// 调试 + JSONObject user = obj.getJSONObject(StorageLoginInfoEnum.User.getKey()); + JSONObject syncKey = obj.getJSONObject(StorageLoginInfoEnum.SyncKey.getKey()); + + core.getLoginInfo().put(StorageLoginInfoEnum.InviteStartCount.getKey(), + obj.getInteger(StorageLoginInfoEnum.InviteStartCount.getKey())); + core.getLoginInfo().put(StorageLoginInfoEnum.SyncKey.getKey(), syncKey); + + JSONArray syncArray = syncKey.getJSONArray("List"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < syncArray.size(); i++) { sb.append(syncArray.getJSONObject(i).getString("Key") + "_" + syncArray.getJSONObject(i).getString("Val") + "|"); } + // 1_661706053|2_661706420|3_661706415|1000_1494151022| String synckey = sb.toString(); - core.getLoginInfo().put("synckey", synckey.substring(0, synckey.length() - 1));// 1_656161336|2_656161626|3_656161313|11_656159955|13_656120033|201_1492273724|1000_1492265953|1001_1492250432|1004_1491805192 - core.setUserName((obj.getJSONObject("User")).getString("UserName")); - core.setNickName((obj.getJSONObject("User")).getString("NickName")); + + // 1_661706053|2_661706420|3_661706415|1000_1494151022 + core.getLoginInfo().put(StorageLoginInfoEnum.synckey.getKey(), synckey.substring(0, synckey.length() - 1));// 1_656161336|2_656161626|3_656161313|11_656159955|13_656120033|201_1492273724|1000_1492265953|1001_1492250432|1004_1491805192 + core.setUserName(user.getString("UserName")); + core.setNickName(user.getString("NickName")); core.setUserSelf(obj.getJSONObject("User")); + return true; } catch (Exception e) { e.printStackTrace(); } - return true; + return false; } @Override public void wxStatusNotify() { - String url = (String) core.getLoginInfo().get("url"); - String passTicket = (String) core.getLoginInfo().get("pass_ticket"); - String mobileUrl = String.format("%s/webwxstatusnotify?lang=zh_CN&pass_ticket=%s", url, passTicket); - Map paramMap = new HashMap(); - @SuppressWarnings("unchecked") - Map> baseRequestMap = (Map>) core.getLoginInfo() - .get("baseRequest"); - paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest")); - paramMap.put("Code", 3); - paramMap.put("FromUserName", core.getUserName()); - paramMap.put("ToUserName", core.getUserName()); - paramMap.put("ClientMsgId", String.valueOf(new Date().getTime())); + // 组装请求URL和参数 + String url = String.format(URLEnum.STATUS_NOTIFY_URL.getUrl(), + core.getLoginInfo().get(StorageLoginInfoEnum.pass_ticket.getKey())); + + Map paramMap = core.getParamMap(); + paramMap.put(StatusNotifyParaEnum.CODE.para(), StatusNotifyParaEnum.CODE.value()); + paramMap.put(StatusNotifyParaEnum.FROM_USERNAME.para(), core.getUserName()); + paramMap.put(StatusNotifyParaEnum.TO_USERNAME.para(), core.getUserName()); + paramMap.put(StatusNotifyParaEnum.CLIENT_MSG_ID.para(), System.currentTimeMillis()); String paramStr = JSON.toJSONString(paramMap); + try { - HttpEntity entity = myHttpClient.doPost(mobileUrl, paramStr); - EntityUtils.toString(entity, "UTF-8"); + HttpEntity entity = httpClient.doPost(url, paramStr); + EntityUtils.toString(entity, "UTF-8");// TODO } catch (Exception e) { - + LOG.error("微信状态通知接口失败!", e); } } @@ -282,40 +294,54 @@ public void run() { } + @Override + public void webWxGetContact() { + String url = String.format(URLEnum.WEB_WX_GET_CONTACT.getUrl(), + core.getLoginInfo().get(StorageLoginInfoEnum.url.getKey())); + Map paramMap = core.getParamMap(); + HttpEntity entity = httpClient.doPost(url, JSON.toJSONString(paramMap)); + + try { + String result = EntityUtils.toString(entity, "UTF-8"); + JSONObject fullFriendsJsonList = JSON.parseObject(result); + + core.setMemberCount(fullFriendsJsonList.getInteger(StorageLoginInfoEnum.MemberCount.getKey())); + JSONArray member = fullFriendsJsonList.getJSONArray(StorageLoginInfoEnum.MemberList.getKey()); + for (Iterator iterator = member.iterator(); iterator.hasNext();) { + JSONObject o = (JSONObject) iterator.next(); + + if ((o.getInteger("VerifyFlag") & 8) != 0) { // 公众号/服务号 + core.getPublicUsersList().add(o); + } else if (Config.API_SPECIAL_USER.contains(o.getString("UserName"))) { // 特殊账号 + core.getSpecialUsersList().add(o); + } else if (o.getString("UserName").indexOf("@@") != -1) { // 群聊 + core.getGroupList().add(o); + } else if (o.getString("UserName").equals(core.getUserSelf().getString("UserName"))) { // 自己 + core.getContactList().remove(o); + } else { // 普通联系人 + core.getContactList().add(o); + } + } + return; + } catch (Exception e) { + LOG.error(e.getMessage(), e); + } + return; + } + /** * 检查登陆状态 - * - * @author https://github.com/yaphone - * @date 2017年4月8日 下午11:22:16 + * + * @param result * @return */ - public String checkLogin() { - String result = ""; - String checkUrl = baseUrl + "/cgi-bin/mmwebwx-bin/login"; - Long localTime = new Date().getTime(); - List params = new ArrayList(); - params.add(new BasicNameValuePair("loginicon", "true")); - params.add(new BasicNameValuePair("uuid", core.getUuid())); - params.add(new BasicNameValuePair("tip", "0")); - params.add(new BasicNameValuePair("r", String.valueOf(localTime / 1579L))); - params.add(new BasicNameValuePair("_", String.valueOf(localTime))); - HttpEntity entity = myHttpClient.doGet(checkUrl, params, true, null); - try { - result = EntityUtils.toString(entity); - } catch (Exception e) { - LOG.info(e.getMessage()); - } + public String checklogin(String result) { String regEx = "window.code=(\\d+)"; Matcher matcher = CommonTool.getMatcher(regEx, result); if (matcher.find()) { - if (matcher.group(1).equals("200")) { // 已登陆 - processLoginInfo(result); - return "200"; - } else if (matcher.group(1).equals("201")) { // 已扫描,未登陆 - return "201"; - } + return matcher.group(1); } - return "400"; + return null; } /** @@ -332,7 +358,7 @@ private void processLoginInfo(String loginContent) { String originalUrl = matcher.group(1); String url = originalUrl.substring(0, originalUrl.lastIndexOf('/')); // https://wx2.qq.com/cgi-bin/mmwebwx-bin core.getLoginInfo().put("url", url); - Map> possibleUrlMap = getPossibleUrlMap(); + Map> possibleUrlMap = this.getPossibleUrlMap(); Iterator>> iterator = possibleUrlMap.entrySet().iterator(); Map.Entry> entry; String fileUrl; @@ -499,13 +525,14 @@ private Map syncCheck() { } String url = String.format("%s/synccheck", syncUrl); List params = new ArrayList(); + for (BaseParaEnum baseRequest : BaseParaEnum.values()) { + params.add(new BasicNameValuePair(baseRequest.para().toLowerCase(), + core.getLoginInfo().get(baseRequest.value()).toString())); + } params.add(new BasicNameValuePair("r", String.valueOf(new Date().getTime()))); - params.add(new BasicNameValuePair("skey", (String) core.getLoginInfo().get("skey"))); - params.add(new BasicNameValuePair("sid", (String) core.getLoginInfo().get("wxsid"))); - params.add(new BasicNameValuePair("uin", (String) core.getLoginInfo().get("wxuin"))); - params.add(new BasicNameValuePair("deviceid", (String) core.getLoginInfo().get("deviceid"))); params.add(new BasicNameValuePair("synckey", (String) core.getLoginInfo().get("synckey"))); params.add(new BasicNameValuePair("_", String.valueOf(new Date().getTime()))); + SleepUtils.sleep(7); try { HttpEntity entity = myHttpClient.doGet(url, params, true, null); if (entity == null) { diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java index 277ecb2..6455de5 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java @@ -7,6 +7,8 @@ import com.alibaba.fastjson.JSONObject; +import cn.zhouyafeng.itchat4j.utils.enums.parameters.BaseParaEnum; + /** * 核心存储类,全局只保存一份,单例模式 * @@ -57,6 +59,21 @@ public static Core getInstance() { String hotReloadDir = "itchat.pkl"; int receivingRetryCount = 5; + /** + * 请求参数 + */ + public Map getParamMap() { + return new HashMap(1) { + { + Map map = new HashMap(); + for (BaseParaEnum baseRequest : BaseParaEnum.values()) { + map.put(baseRequest.para(), getLoginInfo().get(baseRequest.value()).toString()); + } + put("BaseRequest", map); + } + }; + } + public boolean isAlive() { return alive; } diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/SleepUtils.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/SleepUtils.java new file mode 100644 index 0000000..e1ebc6b --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/SleepUtils.java @@ -0,0 +1,20 @@ +package cn.zhouyafeng.itchat4j.utils; + +/** + * Created by xiaoxiaomo on 2017/5/6. + */ +public class SleepUtils { + + /** + * 毫秒为单位 + * @param time + */ + public static void sleep( long time ){ + try { + Thread.sleep( time ); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/ResultEnum.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/ResultEnum.java new file mode 100644 index 0000000..f505b7d --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/ResultEnum.java @@ -0,0 +1,35 @@ +package cn.zhouyafeng.itchat4j.utils.enums; + +/** + * 返回结构枚举类 + *

+ * Created by xiaoxiaomo on 2017/5/6. + */ +public enum ResultEnum { + + SUCCESS("200", "成功"), + WAIT_CONFIRM("201", "请在手机上点击确认"), + WAIT_SCAN("400", "请扫描二维码"); + + private String code; + private String msg; + + ResultEnum(String code, String msg) { + this.code = code; + this.msg = msg; + } + + public String getCode() { + return code; + } + +// public static MsgInfoEnum getCode(String code) { +// switch (code) { +// case "Text": +// return MsgInfoEnum.TEXT; +// default: +// return MsgInfoEnum.VIDEO; +// } +// } + +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/StorageLoginInfoEnum.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/StorageLoginInfoEnum.java new file mode 100644 index 0000000..1d00ea1 --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/StorageLoginInfoEnum.java @@ -0,0 +1,59 @@ +package cn.zhouyafeng.itchat4j.utils.enums; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by xiaoxiaomo on 2017/5/7. + */ +public enum StorageLoginInfoEnum { + + //URL + url("url",new String()), + fileUrl("fileUrl",new String()), + syncUrl("syncUrl",new String()), + + deviceid("deviceid",new String()), //生成15位随机数 + + //baseRequest + skey("skey",new String()), + wxsid("wxsid",new String()), + wxuin("wxuin",new String()), + pass_ticket("pass_ticket",new String()), + + + InviteStartCount("InviteStartCount",new Integer(0)), + User("User",new JSONObject()), + SyncKey("SyncKey",new JSONObject()), + synckey("synckey",new String()), + + + + MemberCount("MemberCount",new String()), + MemberList("MemberList",new JSONArray()), + + + + ; + + private String key; + private Object type; + + StorageLoginInfoEnum(String key, Object type) { + this.key = key; + this.type = type; + } + + public String getKey() { + return key; + } + + + public Object getType() { + return type; + } + +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/URLEnum.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/URLEnum.java new file mode 100644 index 0000000..0979620 --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/URLEnum.java @@ -0,0 +1,36 @@ +package cn.zhouyafeng.itchat4j.utils.enums; + +/** + * URL + * Created by xiaoxiaomo on 2017/5/6. + */ +public enum URLEnum { + + + + BASE_URL("https://login.weixin.qq.com","基本的URL"), + UUID_URL(BASE_URL.url+"/jslogin","UUIDLURL"), + QRCODE_URL(BASE_URL.url+"/qrcode/","初始化URL"), + STATUS_NOTIFY_URL(BASE_URL.url+"/webwxstatusnotify?lang=zh_CN&pass_ticket=%s","微信状态通知"), + LOGIN_URL(BASE_URL.url+"/cgi-bin/mmwebwx-bin/login","登陆URL"), + INIT_URL("%s/webwxinit?r=%s&pass_ticket=%s","初始化URL"), + SYNC_CHECK_URL("/synccheck","检查心跳URL"), + WEB_WX_SYNC_URL("%s/webwxsync?sid=%s&skey=%s&pass_ticket=%s","web微信消息同步URL"), + WEB_WX_GET_CONTACT("%s/webwxgetcontact","web微信获取联系人信息URL"), + WEB_WX_SEND_MSG("%s/webwxsendmsg","发送消息URL"), + + ; + + private String url; + private String msg; + + URLEnum(String url, String msg) { + this.url = url; + this.msg = msg; + } + + + public String getUrl() { + return url; + } +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/BaseParaEnum.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/BaseParaEnum.java new file mode 100644 index 0000000..8f36e8d --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/BaseParaEnum.java @@ -0,0 +1,36 @@ +package cn.zhouyafeng.itchat4j.utils.enums.parameters; + +/** + * + * 基本请求参数 + * 1. webWxInit 初始化 + * 2. wxStatusNotify 微信状态通知 + * + *

+ * Created by xiaoxiaomo on 2017/5/7. + */ +public enum BaseParaEnum { + + Uin("Uin", "wxuin"), + Sid("Sid", "wxsid"), + Skey("Skey", "skey"), + DeviceID("DeviceID", "pass_ticket"); + + private String para; + private String value; + + BaseParaEnum(String para, String value) { + this.para = para; + this.value = value; + } + + public String para() { + return para; + } + + + public Object value() { + return value; + } + +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/LoginParaEnum.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/LoginParaEnum.java new file mode 100644 index 0000000..0c0021a --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/LoginParaEnum.java @@ -0,0 +1,31 @@ +package cn.zhouyafeng.itchat4j.utils.enums.parameters; + +/** + * 登陆 + *

+ * Created by xiaoxiaomo on 2017/5/7. + */ +public enum LoginParaEnum { + + LOGIN_ICON("loginicon", "true"), + UUID("uuid", ""), + TIP("tip", "0"), + R("r", ""), + _("_", ""); + + private String para; + private String value; + + LoginParaEnum(String para, String value) { + this.para = para; + this.value = value; + } + + public String para() { + return para; + } + + public String value() { + return value; + } +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/StatusNotifyParaEnum.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/StatusNotifyParaEnum.java new file mode 100644 index 0000000..9bbdf32 --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/StatusNotifyParaEnum.java @@ -0,0 +1,30 @@ +package cn.zhouyafeng.itchat4j.utils.enums.parameters; + +/** + * 状态通知 + *

+ * Created by xiaoxiaomo on 2017/5/7. + */ +public enum StatusNotifyParaEnum { + + CODE("Code", "3"), + FROM_USERNAME("FromUserName", ""), + TO_USERNAME("ToUserName", ""), + CLIENT_MSG_ID("ClientMsgId", ""); //时间戳 + + private String para; + private String value; + + StatusNotifyParaEnum(String para, String value) { + this.para = para; + this.value = value; + } + + public String para() { + return para; + } + + public String value() { + return value; + } +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/UUIDParaEnum.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/UUIDParaEnum.java new file mode 100644 index 0000000..ef716e8 --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/parameters/UUIDParaEnum.java @@ -0,0 +1,30 @@ +package cn.zhouyafeng.itchat4j.utils.enums.parameters; + +/** + * UUID + *

+ * Created by xiaoxiaomo on 2017/5/7. + */ +public enum UUIDParaEnum { + + APP_ID("appid", "wx782c26e4c19acffb"), + FUN("fun", "new"), + LANG("lang", "zh_CN"), + _("_", "时间戳"); + + private String para; + private String value; + + UUIDParaEnum(String para, String value) { + this.para = para; + this.value = value; + } + + public String para() { + return para; + } + + public String value() { + return value; + } +} diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties index 3cee63d..dc30ec0 100644 --- a/src/main/resources/log4j.properties +++ b/src/main/resources/log4j.properties @@ -1,11 +1,6 @@ -#config root logger -log4j.rootLogger = INFO,system.out -log4j.appender.system.out=org.apache.log4j.ConsoleAppender -log4j.appender.system.out.layout=org.apache.log4j.PatternLayout -log4j.appender.system.out.layout.ConversionPattern=MINAServer Logger-->%5p{%F:%L}-%m%n - -#config this Project.file logger -log4j.logger.thisProject.file=ALL,thisProject.file.out -log4j.appender.thisProject.file.out=org.apache.log4j.DailyRollingFileAppender -log4j.appender.thisProject.file.out.File=logContentFile.log -log4j.appender.thisProject.file.out.layout=org.apache.log4j.PatternLayout \ No newline at end of file +log4j.rootLogger=INFO, stdout + +log4j.appender.stdout = org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout = org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern = %d %-5p => %m%n + diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java index beb7f75..a8640ea 100644 --- a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java @@ -22,7 +22,7 @@ * */ public class SimpleDemo implements IMsgHandlerFace { - Logger logger = Logger.getLogger(SimpleDemo.class); + Logger LOG = Logger.getLogger(SimpleDemo.class); @Override public String textMsgHandle(JSONObject msg) { @@ -36,7 +36,7 @@ public String textMsgHandle(JSONObject msg) { // MessageTools.sendFileMsgByNickName("yaphone", txtFilePath); // logger.info("info" + msg.toJSONString()); // System.out.println("*************"); - logger.info("debug" + msg.toJSONString()); + LOG.info("debug" + msg.toJSONString()); String text = msg.getString("Text"); return text; // return null; diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java new file mode 100644 index 0000000..546e102 --- /dev/null +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java @@ -0,0 +1,88 @@ +package cn.zhouyafeng.itchat4j.demo.demo2; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.fastjson.JSONObject; + +import cn.zhouyafeng.itchat4j.Wechat2; +import cn.zhouyafeng.itchat4j.api.MessageTools; +import cn.zhouyafeng.itchat4j.api.WechatTools; +import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; +import cn.zhouyafeng.itchat4j.utils.MsgType; +import cn.zhouyafeng.itchat4j.utils.tools.DownloadTools; + +/** + * + * @author https://github.com/yaphone + * @date 创建时间:2017年5月13日 下午2:44:58 + * @version 1.0 + * + */ +public class SimpleDemo2 implements IMsgHandlerFace { + + private static final Logger LOG = LoggerFactory.getLogger(SimpleDemo2.class); + + @Override + public String textMsgHandle(JSONObject msg) { + String docFilePath = "D:/itchat4j/pic/test.docx"; + // String pngFilePath = "D:/itchat4j/pic/test.png"; + // String pdfFilePath = "D:/itchat4j/pic/测试.pdf"; + // String txtFilePath = "D:/itchat4j/pic/test.txt"; + MessageTools.sendFileMsgByUserId(msg.getString("FromUserName"), docFilePath); + // MessageTools.sendFileMsgByNickName("yaphone", pngFilePath); + // MessageTools.sendFileMsgByNickName("yaphone", pdfFilePath); + // MessageTools.sendFileMsgByNickName("yaphone", txtFilePath); + // logger.info("info" + msg.toJSONString()); + // System.out.println("*************"); + if (!msg.getBoolean("groupMsg")) { + // MessageTools.sendFileMsgByUserId(msg.getString("FromUserName"), + // docFilePath); + LOG.info("联系人总数: " + WechatTools.getContactList().size()); + String text = msg.getString("Text"); + return text; + } + return null; + // return null; + } + + @Override + public String picMsgHandle(JSONObject msg) { + String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String picPath = "D://itchat4j/pic" + File.separator + fileName + ".jpg"; + DownloadTools.getDownloadFn(msg, MsgType.PIC, picPath); + return "图片保存成功"; + } + + @Override + public String voiceMsgHandle(JSONObject msg) { + String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String voicePath = "D://itchat4j/voice" + File.separator + fileName + ".mp3"; + DownloadTools.getDownloadFn(msg, MsgType.VOICE, voicePath); + return "声音保存成功"; + } + + @Override + public String viedoMsgHandle(JSONObject msg) { + System.out.println(msg); + String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String viedoPath = "D://itchat4j/viedo" + File.separator + fileName + ".mp4"; + DownloadTools.getDownloadFn(msg, MsgType.VIEDO, viedoPath); + return "视频保存成功"; + } + + @Override + public String nameCardMsgHandle(JSONObject msg) { + return "收到名片消息"; + } + + public static void main(String[] args) { + IMsgHandlerFace msgHandler = new SimpleDemo2(); + Wechat2 wechat = new Wechat2(msgHandler, "D://itchat4j/login"); + wechat.start(); + } +} From e893df70154722d508a3e5964a998c7c1d1cd963 Mon Sep 17 00:00:00 2001 From: yaphone Date: Sun, 14 May 2017 01:04:55 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E7=BB=93=E6=9E=84=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/zhouyafeng/itchat4j/Wechat.java | 12 ++-- .../zhouyafeng/itchat4j/api/MessageTools.java | 55 +++++++------- .../zhouyafeng/itchat4j/core/MsgCenter.java | 21 +++--- .../service/impl/LoginServiceImpl.java | 71 ++++++++----------- .../cn/zhouyafeng/itchat4j/utils/MsgType.java | 11 --- .../itchat4j/utils/MyHttpClient.java | 2 + .../itchat4j/utils/enums/MsgTypeEnum.java | 34 +++++++++ .../itchat4j/utils/enums/URLEnum.java | 4 ++ .../itchat4j/utils/tools/DownloadTools.java | 15 ++-- .../zhouyafeng/itchat4j/demo/SimpleDemo.java | 8 +-- .../zhouyafeng/itchat4j/demo/TulingRobot.java | 6 +- .../itchat4j/demo/demo2/SimpleDemo2.java | 8 +-- 12 files changed, 134 insertions(+), 113 deletions(-) create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/enums/MsgTypeEnum.java diff --git a/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java b/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java index 943826a..c8697cd 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java @@ -10,7 +10,7 @@ import cn.zhouyafeng.itchat4j.service.ILoginService; import cn.zhouyafeng.itchat4j.service.impl.LoginServiceImpl; import cn.zhouyafeng.itchat4j.utils.Core; -import cn.zhouyafeng.itchat4j.utils.MsgType; +import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; /** * 主类,初始化工作 @@ -46,23 +46,23 @@ public void run() { if (core.getMsgList().get(0).getString("Content").length() > 0) { JSONObject msg = core.getMsgList().get(0); if (msg.getString("Type") != null) { - if (msg.getString("Type").equals(MsgType.TEXT)) { + if (msg.getString("Type").equals(MsgTypeEnum.TEXT.getType())) { String result = msgHandler.textMsgHandle(msg); MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgType.PIC)) { + } else if (msg.getString("Type").equals(MsgTypeEnum.PIC.getType())) { String result = msgHandler.picMsgHandle(msg); MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgType.VOICE)) { + } else if (msg.getString("Type").equals(MsgTypeEnum.VOICE.getType())) { String result = msgHandler.voiceMsgHandle(msg); MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgType.VIEDO)) { + } else if (msg.getString("Type").equals(MsgTypeEnum.VIEDO.getType())) { String result = msgHandler.viedoMsgHandle(msg); MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgType.NAMECARD)) { + } else if (msg.getString("Type").equals(MsgTypeEnum.NAMECARD.getType())) { String result = msgHandler.nameCardMsgHandle(msg); MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); diff --git a/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java b/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java index 9ff1e2b..6aef96a 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java @@ -10,6 +10,7 @@ import javax.activation.MimetypesFileTypeMap; +import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.HttpMultipartMode; @@ -22,6 +23,7 @@ import cn.zhouyafeng.itchat4j.utils.Config; import cn.zhouyafeng.itchat4j.utils.Core; import cn.zhouyafeng.itchat4j.utils.MyHttpClient; +import cn.zhouyafeng.itchat4j.utils.enums.URLEnum; /** * 消息处理类 @@ -46,7 +48,7 @@ public class MessageTools { */ private static void sendMsg(String text, String toUserName) { logger.info(String.format("Request to send a text message to %s: %s", toUserName, text)); - sendRawMsg(1, text, toUserName); + webWxSendMsg(1, text, toUserName); } /** @@ -73,7 +75,7 @@ public static boolean sendMsgByNickName(String text, String nickName) { if (nickName != null) { String toUserName = WechatTools.getUserNameByNickName(nickName); if (toUserName != null) { - sendRawMsg(1, text, toUserName); + webWxSendMsg(1, text, toUserName); return true; } } @@ -90,14 +92,8 @@ public static boolean sendMsgByNickName(String text, String nickName) { * @param content * @param toUserName */ - public static void sendRawMsg(int msgType, String content, String toUserName) { - String url = String.format("%s/webwxsendmsg", core.getLoginInfo().get("url")); - - Map paramMap = new HashMap(); - @SuppressWarnings("unchecked") - Map> baseRequestMap = (Map>) core.getLoginInfo() - .get("baseRequest"); - paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest")); + public static void webWxSendMsg(int msgType, String content, String toUserName) { + String url = String.format(URLEnum.WEB_WX_SEND_MSG.getUrl(), core.getLoginInfo().get("url")); Map msgMap = new HashMap(); msgMap.put("Type", msgType); msgMap.put("Content", content); @@ -105,12 +101,13 @@ public static void sendRawMsg(int msgType, String content, String toUserName) { msgMap.put("ToUserName", toUserName == null ? core.getUserName() : toUserName); msgMap.put("LocalID", new Date().getTime() * 10); msgMap.put("ClientMsgId", new Date().getTime() * 10); + Map paramMap = core.getParamMap(); paramMap.put("Msg", msgMap); paramMap.put("Scene", 0); try { String paramStr = JSON.toJSONString(paramMap); HttpEntity entity = myHttpClient.doPost(url, paramStr); - EntityUtils.toString(entity, "UTF-8"); + EntityUtils.toString(entity, Consts.UTF_8); } catch (Exception e) { logger.info(e.getMessage()); } @@ -133,13 +130,13 @@ public static void sendRawMsg(int msgType, String content, String toUserName) { * @param filePath * @return */ - private static JSONObject uploadMediaToServer(String filePath) { + private static JSONObject webWxUploadMedia(String filePath) { File f = new File(filePath); if (!f.exists() && f.isFile()) { logger.info("file is not exist"); return null; } - String url = (String) core.getLoginInfo().get("fileUrl") + "/webwxuploadmedia?f=json"; + String url = String.format(URLEnum.WEB_WX_UPLOAD_MEDIA.getUrl(), core.getLoginInfo().get("fileUrl")); String mimeType = new MimetypesFileTypeMap().getContentType(f); String mediaType = ""; if (mimeType == null) { @@ -158,11 +155,8 @@ private static JSONObject uploadMediaToServer(String filePath) { return null; } - Map paramMap = new HashMap(); - @SuppressWarnings("unchecked") - Map> baseRequestMap = (Map>) core.getLoginInfo() - .get("baseRequest"); - paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest")); + Map paramMap = core.getParamMap(); + paramMap.put("ClientMediaId", clientMediaId); paramMap.put("TotalLen", fileSize); paramMap.put("StartPos", 0); @@ -186,7 +180,7 @@ private static JSONObject uploadMediaToServer(String filePath) { HttpEntity entity = myHttpClient.doPostFile(url, reqEntity); if (entity != null) { try { - String result = EntityUtils.toString(entity, "UTF-8"); + String result = EntityUtils.toString(entity, Consts.UTF_8); return JSON.parseObject(result); } catch (Exception e) { logger.info(e.getMessage()); @@ -222,7 +216,7 @@ public static boolean sendPicMsgByNickName(String nickName, String filePath) { * @return */ public static boolean sendPicMsgByUserId(String userId, String filePath) { - JSONObject responseObj = uploadMediaToServer(filePath); + JSONObject responseObj = webWxUploadMedia(filePath); if (responseObj != null) { String mediaId = responseObj.getString("MediaId"); if (mediaId != null) { @@ -261,7 +255,7 @@ private static boolean webWxSendMsgImg(String userId, String mediaId) { HttpEntity entity = myHttpClient.doPost(url, paramStr); if (entity != null) { try { - String result = EntityUtils.toString(entity, "UTF-8"); + String result = EntityUtils.toString(entity, Consts.UTF_8); return JSON.parseObject(result).getJSONObject("BaseResponse").getInteger("Ret") == 0; } catch (Exception e) { logger.info(e.getMessage()); @@ -289,7 +283,7 @@ public static boolean sendFileMsgByUserId(String userId, String filePath) { data.put("attachid", ""); data.put("type", "6"); // APPMSGTYPE_ATTACH data.put("fileext", title.split("\\.")[1]); // 文件后缀 - JSONObject responseObj = uploadMediaToServer(filePath); + JSONObject responseObj = webWxUploadMedia(filePath); if (responseObj != null) { data.put("totallen", responseObj.getString("StartPos")); data.put("attachid", responseObj.getString("MediaId")); @@ -341,18 +335,23 @@ private static boolean webWxSendAppMsg(String userId, Map data) msgMap.put("ToUserName", userId); msgMap.put("LocalID", clientMsgId); msgMap.put("ClientMsgId", clientMsgId); - Map paramMap = new HashMap(); - @SuppressWarnings("unchecked") - Map> baseRequestMap = (Map>) core.getLoginInfo() - .get("baseRequest"); - paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest")); + /* + * Map paramMap = new HashMap(); + * + * @SuppressWarnings("unchecked") Map> + * baseRequestMap = (Map>) + * core.getLoginInfo() .get("baseRequest"); paramMap.put("BaseRequest", + * baseRequestMap.get("BaseRequest")); + */ + + Map paramMap = core.getParamMap(); paramMap.put("Msg", msgMap); paramMap.put("Scene", 0); String paramStr = JSON.toJSONString(paramMap); HttpEntity entity = myHttpClient.doPost(url, paramStr); if (entity != null) { try { - String result = EntityUtils.toString(entity, "UTF-8"); + String result = EntityUtils.toString(entity, Consts.UTF_8); return JSON.parseObject(result).getJSONObject("BaseResponse").getInteger("Ret") == 0; } catch (Exception e) { logger.info(e.getMessage()); diff --git a/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java b/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java index aee2779..f5355f8 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java @@ -13,6 +13,7 @@ import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; import cn.zhouyafeng.itchat4j.utils.Core; import cn.zhouyafeng.itchat4j.utils.MsgType; +import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; import cn.zhouyafeng.itchat4j.utils.tools.CommonTool; public class MsgCenter { @@ -64,24 +65,24 @@ public static JSONArray produceMsg(JSONArray msgList) { msg.put("Type", "Map"); msg.put("Text", data); } else { - msg.put("Type", MsgType.TEXT); + msg.put("Type", MsgTypeEnum.TEXT); msg.put("Text", m.getString("Content")); } m.put("Type", msg.getString("Type")); m.put("Text", msg.getString("Text")); } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_IMAGE || m.getInteger("MsgType") == MsgType.MSGTYPE_EMOTICON) { // 图片消息 - m.put("Type", MsgType.PIC); + m.put("Type", MsgTypeEnum.PIC.getType()); } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_VOICE) { // 语音消息 - m.put("Type", MsgType.VOICE); + m.put("Type", MsgTypeEnum.VOICE.getType()); } else if (m.getInteger("MsgType") == 37) {// friends 好友确认消息 } else if (m.getInteger("MsgType") == 42) { // 共享名片 - m.put("Type", MsgType.NAMECARD); + m.put("Type", MsgTypeEnum.NAMECARD.getType()); } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_VIDEO || m.getInteger("MsgType") == MsgType.MSGTYPE_MICROVIDEO) {// viedo - m.put("Type", MsgType.VIEDO); + m.put("Type", MsgTypeEnum.VIEDO.getType()); } else if (m.getInteger("MsgType") == 49) { // sharing 分享链接 } else if (m.getInteger("MsgType") == 51) {// phone init 微信初始化消息 @@ -105,19 +106,19 @@ public static void handleMsg(IMsgHandlerFace msgHandler) { if (core.getMsgList().get(0).getString("Content").length() > 0) { JSONObject msg = core.getMsgList().get(0); if (msg.getString("Type") != null) { - if (msg.getString("Type").equals(MsgType.TEXT)) { + if (msg.getString("Type").equals(MsgTypeEnum.TEXT.getType())) { String result = msgHandler.textMsgHandle(msg); MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgType.PIC)) { + } else if (msg.getString("Type").equals(MsgTypeEnum.PIC.getType())) { String result = msgHandler.picMsgHandle(msg); MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgType.VOICE)) { + } else if (msg.getString("Type").equals(MsgTypeEnum.VOICE.getType())) { String result = msgHandler.voiceMsgHandle(msg); MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgType.VIEDO)) { + } else if (msg.getString("Type").equals(MsgTypeEnum.VIEDO.getType())) { String result = msgHandler.viedoMsgHandle(msg); MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgType.NAMECARD)) { + } else if (msg.getString("Type").equals(MsgTypeEnum.NAMECARD.getType())) { String result = msgHandler.nameCardMsgHandle(msg); MessageTools.sendMsgById(result, core.getMsgList().get(0).getString("FromUserName")); } diff --git a/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java b/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java index 66513b6..87917b2 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java @@ -13,6 +13,7 @@ import java.util.Random; import java.util.regex.Matcher; +import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; @@ -49,7 +50,6 @@ */ public class LoginServiceImpl implements ILoginService { private static Logger LOG = LoggerFactory.getLogger(LoginServiceImpl.class); - private String baseUrl = Config.BASE_URL; private Core core = Core.getInstance(); private MyHttpClient httpClient = core.getMyHttpClient(); @@ -166,7 +166,7 @@ public boolean webWxInit() { // 请求初始化接口 HttpEntity entity = httpClient.doPost(url, JSON.toJSONString(paramMap)); try { - String result = EntityUtils.toString(entity, "UTF-8"); + String result = EntityUtils.toString(entity, Consts.UTF_8); JSONObject obj = JSON.parseObject(result); LOG.info(obj.toString());// 调试 @@ -213,7 +213,7 @@ public void wxStatusNotify() { try { HttpEntity entity = httpClient.doPost(url, paramStr); - EntityUtils.toString(entity, "UTF-8");// TODO + EntityUtils.toString(entity, Consts.UTF_8);// TODO } catch (Exception e) { LOG.error("微信状态通知接口失败!", e); } @@ -302,7 +302,7 @@ public void webWxGetContact() { HttpEntity entity = httpClient.doPost(url, JSON.toJSONString(paramMap)); try { - String result = EntityUtils.toString(entity, "UTF-8"); + String result = EntityUtils.toString(entity, Consts.UTF_8); JSONObject fullFriendsJsonList = JSON.parseObject(result); core.setMemberCount(fullFriendsJsonList.getInteger(StorageLoginInfoEnum.MemberCount.getKey())); @@ -381,7 +381,6 @@ private void processLoginInfo(String loginContent) { core.getLoginInfo().put("deviceid", "e" + String.valueOf(new Random().nextLong()).substring(1, 16)); // 生成15位随机数 core.getLoginInfo().put("BaseRequest", new ArrayList()); String text = ""; - // // 禁止重定向 try { HttpEntity entity = myHttpClient.doGet(originalUrl, null, false, null); @@ -391,23 +390,19 @@ private void processLoginInfo(String loginContent) { return; } Document doc = CommonTool.xmlParser(text); - Map> BaseRequest = new HashMap>(); - Map baseRequest = new HashMap(); if (doc != null) { - core.getLoginInfo().put("skey", - doc.getElementsByTagName("skey").item(0).getFirstChild().getNodeValue()); - baseRequest.put("Skey", (String) core.getLoginInfo().get("skey")); - core.getLoginInfo().put("wxsid", - doc.getElementsByTagName("wxsid").item(0).getFirstChild().getNodeValue()); - baseRequest.put("Sid", (String) core.getLoginInfo().get("wxsid")); - core.getLoginInfo().put("wxuin", - doc.getElementsByTagName("wxuin").item(0).getFirstChild().getNodeValue()); - baseRequest.put("Uin", (String) core.getLoginInfo().get("wxuin")); - core.getLoginInfo().put("pass_ticket", - doc.getElementsByTagName("pass_ticket").item(0).getFirstChild().getNodeValue()); - baseRequest.put("DeviceID", (String) core.getLoginInfo().get("deviceid")); - BaseRequest.put("BaseRequest", baseRequest); - core.getLoginInfo().put("baseRequest", BaseRequest); + core.getLoginInfo().put(StorageLoginInfoEnum.skey.getKey(), + doc.getElementsByTagName(StorageLoginInfoEnum.skey.getKey()).item(0).getFirstChild() + .getNodeValue()); + core.getLoginInfo().put(StorageLoginInfoEnum.wxsid.getKey(), + doc.getElementsByTagName(StorageLoginInfoEnum.wxsid.getKey()).item(0).getFirstChild() + .getNodeValue()); + core.getLoginInfo().put(StorageLoginInfoEnum.wxuin.getKey(), + doc.getElementsByTagName(StorageLoginInfoEnum.wxuin.getKey()).item(0).getFirstChild() + .getNodeValue()); + core.getLoginInfo().put(StorageLoginInfoEnum.pass_ticket.getKey(), + doc.getElementsByTagName(StorageLoginInfoEnum.pass_ticket.getKey()).item(0).getFirstChild() + .getNodeValue()); } } @@ -472,34 +467,34 @@ private Map> getPossibleUrlMap() { */ private JSONObject webWxSync() { JSONObject result = null; - String url = String.format("%s/webwxsync?sid=%s&skey=%s&pass_ticket=%s", core.getLoginInfo().get("url"), - core.getLoginInfo().get("wxsid"), core.getLoginInfo().get("skey"), - core.getLoginInfo().get("pass_ticket")); - Map paramMap = new HashMap(); - @SuppressWarnings("unchecked") - Map> baseRequestMap = (Map>) core.getLoginInfo() - .get("baseRequest"); - paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest")); - paramMap.put("SyncKey", core.getLoginInfo().get("SyncKey")); + String url = String.format(URLEnum.WEB_WX_SYNC_URL.getUrl(), + core.getLoginInfo().get(StorageLoginInfoEnum.url.getKey()), + core.getLoginInfo().get(StorageLoginInfoEnum.wxsid.getKey()), + core.getLoginInfo().get(StorageLoginInfoEnum.skey.getKey()), + core.getLoginInfo().get(StorageLoginInfoEnum.pass_ticket.getKey())); + Map paramMap = core.getParamMap(); + paramMap.put(StorageLoginInfoEnum.SyncKey.getKey(), + core.getLoginInfo().get(StorageLoginInfoEnum.SyncKey.getKey())); paramMap.put("rr", -new Date().getTime() / 1000); String paramStr = JSON.toJSONString(paramMap); try { HttpEntity entity = myHttpClient.doPost(url, paramStr); - String text = EntityUtils.toString(entity, "UTF-8"); + String text = EntityUtils.toString(entity, Consts.UTF_8); JSONObject obj = JSON.parseObject(text); if (obj.getJSONObject("BaseResponse").getInteger("Ret") != 0) { result = null; } else { result = obj; - core.getLoginInfo().put("SyncKey", obj.getJSONObject("SyncCheckKey")); - JSONArray syncArray = obj.getJSONObject("SyncKey").getJSONArray("List"); + core.getLoginInfo().put(StorageLoginInfoEnum.SyncKey.getKey(), obj.getJSONObject("SyncCheckKey")); + JSONArray syncArray = obj.getJSONObject(StorageLoginInfoEnum.SyncKey.getKey()).getJSONArray("List"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < syncArray.size(); i++) { sb.append(syncArray.getJSONObject(i).getString("Key") + "_" + syncArray.getJSONObject(i).getString("Val") + "|"); } String synckey = sb.toString(); - core.getLoginInfo().put("synckey", synckey.substring(0, synckey.length() - 1));// 1_656161336|2_656161626|3_656161313|11_656159955|13_656120033|201_1492273724|1000_1492265953|1001_1492250432|1004_1491805192 + core.getLoginInfo().put(StorageLoginInfoEnum.synckey.getKey(), + synckey.substring(0, synckey.length() - 1));// 1_656161336|2_656161626|3_656161313|11_656159955|13_656120033|201_1492273724|1000_1492265953|1001_1492250432|1004_1491805192 } } catch (Exception e) { LOG.info(e.getMessage()); @@ -518,12 +513,8 @@ private JSONObject webWxSync() { */ private Map syncCheck() { Map resultMap = new HashMap(); - String syncUrl = (String) core.getLoginInfo().get("syncUrl"); - // String syncUrl = "https://webpush.wx2.qq.com/cgi-bin/mmwebwx-bin"; - if (syncUrl == null || syncUrl.equals("")) { - syncUrl = (String) core.getLoginInfo().get("url"); - } - String url = String.format("%s/synccheck", syncUrl); + // 组装请求URL和参数 + String url = core.getLoginInfo().get(StorageLoginInfoEnum.syncUrl.getKey()) + URLEnum.SYNC_CHECK_URL.getUrl(); List params = new ArrayList(); for (BaseParaEnum baseRequest : BaseParaEnum.values()) { params.add(new BasicNameValuePair(baseRequest.para().toLowerCase(), diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/MsgType.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/MsgType.java index 7f0e551..fc9da54 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/MsgType.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/MsgType.java @@ -29,15 +29,4 @@ public class MsgType { public static final int MSGTYPE_SYS = 10000; public static final int MSGTYPE_RECALLED = 10002; - // 文本信息 - public static String TEXT = "Text"; - // 图片信息 - public static String PIC = "Pic"; - // 语音信息 - public static String VOICE = "Voice"; - // 小视频消息 - public static String VIEDO = "Video"; - // name card 明片消息 - public static String NAMECARD = "NameCard"; - } diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/MyHttpClient.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/MyHttpClient.java index d5e7a66..431a154 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/MyHttpClient.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/MyHttpClient.java @@ -99,6 +99,8 @@ public HttpEntity doGet(String url, List params, boolean red if (params != null) { String paramStr = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8)); httpGet = new HttpGet(url + "?" + paramStr); + System.out.println(httpGet.getURI()); + } else { httpGet = new HttpGet(url); } diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/MsgTypeEnum.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/MsgTypeEnum.java new file mode 100644 index 0000000..82caca5 --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/MsgTypeEnum.java @@ -0,0 +1,34 @@ +package cn.zhouyafeng.itchat4j.utils.enums; + +/** + * 消息类型枚举类 + * + * @author https://github.com/yaphone + * @date 创建时间:2017年5月13日 下午11:53:00 + * @version 1.0 + * + */ +public enum MsgTypeEnum { + TEXT("Text", "文本消息"), + PIC("Pic", "图片消息"), + VOICE("Voice", "语音消息"), + VIEDO("Viedo", "小视频消息"), + NAMECARD("NameCard", "名片消息"); + + private String type; + private String code; + + MsgTypeEnum(String type, String code) { + this.type = type; + this.code = code; + } + + public String getType() { + return type; + } + + public String getCode() { + return code; + } + +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/URLEnum.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/URLEnum.java index 0979620..1656b16 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/URLEnum.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/URLEnum.java @@ -18,6 +18,10 @@ public enum URLEnum { WEB_WX_SYNC_URL("%s/webwxsync?sid=%s&skey=%s&pass_ticket=%s","web微信消息同步URL"), WEB_WX_GET_CONTACT("%s/webwxgetcontact","web微信获取联系人信息URL"), WEB_WX_SEND_MSG("%s/webwxsendmsg","发送消息URL"), + WEB_WX_UPLOAD_MEDIA("%s/webwxuploadmedia?f=json", "上传文件到服务器"), + WEB_WX_GET_MSG_IMG("%s/webwxgetmsgimg", "下载图片消息"), + WEB_WX_GET_VOICE("%s/webwxgetvoice", "下载语音消息"), + WEB_WX_GET_VIEDO("%s/webwxgetvideo", "下载语音消息") ; diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/DownloadTools.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/DownloadTools.java index 7127d9f..426e5b8 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/DownloadTools.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/DownloadTools.java @@ -15,8 +15,9 @@ import com.alibaba.fastjson.JSONObject; import cn.zhouyafeng.itchat4j.utils.Core; -import cn.zhouyafeng.itchat4j.utils.MsgType; import cn.zhouyafeng.itchat4j.utils.MyHttpClient; +import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; +import cn.zhouyafeng.itchat4j.utils.enums.URLEnum; /** * 下载工具类 @@ -45,13 +46,13 @@ public static Object getDownloadFn(JSONObject msg, String type, String path) { Map headerMap = new HashMap(); List params = new ArrayList(); String url = ""; - if (type.equals(MsgType.PIC)) { - url = String.format("%s/webwxgetmsgimg", (String) core.getLoginInfo().get("url")); - } else if (type.equals(MsgType.VOICE)) { - url = String.format("%s/webwxgetvoice", (String) core.getLoginInfo().get("url")); - } else if (type.equals(MsgType.VIEDO)) { + if (type.equals(MsgTypeEnum.PIC.getType())) { + url = String.format(URLEnum.WEB_WX_GET_MSG_IMG.getUrl(), core.getLoginInfo().get("url")); + } else if (type.equals(MsgTypeEnum.VOICE.getType())) { + url = String.format(URLEnum.WEB_WX_GET_VOICE.getUrl(), core.getLoginInfo().get("url")); + } else if (type.equals(MsgTypeEnum.VIEDO.getType())) { headerMap.put("Range", "bytes=0-"); - url = String.format("%s/webwxgetvideo", (String) core.getLoginInfo().get("url")); + url = String.format(URLEnum.WEB_WX_GET_VIEDO.getUrl(), core.getLoginInfo().get("url")); } params.add(new BasicNameValuePair("msgid", msg.getString("NewMsgId"))); params.add(new BasicNameValuePair("skey", (String) core.getLoginInfo().get("skey"))); diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java index a8640ea..847de29 100644 --- a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java @@ -10,7 +10,7 @@ import cn.zhouyafeng.itchat4j.Wechat; import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; -import cn.zhouyafeng.itchat4j.utils.MsgType; +import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; import cn.zhouyafeng.itchat4j.utils.tools.DownloadTools; /** @@ -46,7 +46,7 @@ public String textMsgHandle(JSONObject msg) { public String picMsgHandle(JSONObject msg) { String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); String picPath = "D://itchat4j/pic" + File.separator + fileName + ".jpg"; - DownloadTools.getDownloadFn(msg, MsgType.PIC, picPath); + DownloadTools.getDownloadFn(msg, MsgTypeEnum.PIC.getType(), picPath); return "图片保存成功"; } @@ -54,7 +54,7 @@ public String picMsgHandle(JSONObject msg) { public String voiceMsgHandle(JSONObject msg) { String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); String voicePath = "D://itchat4j/voice" + File.separator + fileName + ".mp3"; - DownloadTools.getDownloadFn(msg, MsgType.VOICE, voicePath); + DownloadTools.getDownloadFn(msg, MsgTypeEnum.VOICE.getType(), voicePath); return "声音保存成功"; } @@ -63,7 +63,7 @@ public String viedoMsgHandle(JSONObject msg) { System.out.println(msg); String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); String viedoPath = "D://itchat4j/viedo" + File.separator + fileName + ".mp4"; - DownloadTools.getDownloadFn(msg, MsgType.VIEDO, viedoPath); + DownloadTools.getDownloadFn(msg, MsgTypeEnum.VIEDO.getType(), viedoPath); return "视频保存成功"; } diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java index d69f6b5..348abc6 100644 --- a/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java @@ -15,8 +15,8 @@ import cn.zhouyafeng.itchat4j.Wechat; import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; import cn.zhouyafeng.itchat4j.utils.Core; -import cn.zhouyafeng.itchat4j.utils.MsgType; import cn.zhouyafeng.itchat4j.utils.MyHttpClient; +import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; import cn.zhouyafeng.itchat4j.utils.tools.DownloadTools; /** @@ -66,7 +66,7 @@ public String picMsgHandle(JSONObject msg) { public String voiceMsgHandle(JSONObject msg) { String fileName = String.valueOf(new Date().getTime()); String voicePath = "D://itchat4j/voice" + File.separator + fileName + ".mp3"; - DownloadTools.getDownloadFn(msg, MsgType.VOICE, voicePath); + DownloadTools.getDownloadFn(msg, MsgTypeEnum.VOICE.getType(), voicePath); return "收到语音"; } @@ -74,7 +74,7 @@ public String voiceMsgHandle(JSONObject msg) { public String viedoMsgHandle(JSONObject msg) { String fileName = String.valueOf(new Date().getTime()); String viedoPath = "D://itchat4j/viedo" + File.separator + fileName + ".mp4"; - DownloadTools.getDownloadFn(msg, MsgType.VIEDO, viedoPath); + DownloadTools.getDownloadFn(msg, MsgTypeEnum.VIEDO.getType(), viedoPath); return "收到视频"; } diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java index 546e102..f7c6558 100644 --- a/src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java @@ -13,7 +13,7 @@ import cn.zhouyafeng.itchat4j.api.MessageTools; import cn.zhouyafeng.itchat4j.api.WechatTools; import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; -import cn.zhouyafeng.itchat4j.utils.MsgType; +import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; import cn.zhouyafeng.itchat4j.utils.tools.DownloadTools; /** @@ -54,7 +54,7 @@ public String textMsgHandle(JSONObject msg) { public String picMsgHandle(JSONObject msg) { String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); String picPath = "D://itchat4j/pic" + File.separator + fileName + ".jpg"; - DownloadTools.getDownloadFn(msg, MsgType.PIC, picPath); + DownloadTools.getDownloadFn(msg, MsgTypeEnum.PIC.getType(), picPath); return "图片保存成功"; } @@ -62,7 +62,7 @@ public String picMsgHandle(JSONObject msg) { public String voiceMsgHandle(JSONObject msg) { String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); String voicePath = "D://itchat4j/voice" + File.separator + fileName + ".mp3"; - DownloadTools.getDownloadFn(msg, MsgType.VOICE, voicePath); + DownloadTools.getDownloadFn(msg, MsgTypeEnum.VOICE.getType(), voicePath); return "声音保存成功"; } @@ -71,7 +71,7 @@ public String viedoMsgHandle(JSONObject msg) { System.out.println(msg); String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); String viedoPath = "D://itchat4j/viedo" + File.separator + fileName + ".mp4"; - DownloadTools.getDownloadFn(msg, MsgType.VIEDO, viedoPath); + DownloadTools.getDownloadFn(msg, MsgTypeEnum.VIEDO.getType(), viedoPath); return "视频保存成功"; } From d1b583537e206a1354f9996281435e90cfa512a6 Mon Sep 17 00:00:00 2001 From: yaphone Date: Sun, 14 May 2017 17:49:37 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=8C=85=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 63 +- .../java/cn/zhouyafeng/itchat4j/Wechat.java | 75 +-- .../java/cn/zhouyafeng/itchat4j/Wechat2.java | 33 - .../zhouyafeng/itchat4j/api/MessageTools.java | 23 +- .../zhouyafeng/itchat4j/api/WechatTools.java | 2 +- .../zhouyafeng/itchat4j/components/Login.java | 584 ------------------ .../itchat4j/controller/LoginController.java | 6 +- .../itchat4j/{utils => core}/Core.java | 8 +- .../zhouyafeng/itchat4j/core/MsgCenter.java | 59 +- .../service/impl/LoginServiceImpl.java | 42 +- .../itchat4j/utils/MsgCodeEnum.java | 68 ++ .../cn/zhouyafeng/itchat4j/utils/MsgType.java | 32 - .../itchat4j/utils/MyHttpClient.java | 1 - .../itchat4j/utils/enums/RetCodeEnum.java | 30 + .../{CommonTool.java => CommonTools.java} | 2 +- .../itchat4j/utils/tools/DownloadTools.java | 2 +- .../zhouyafeng/itchat4j/demo/TulingRobot.java | 4 +- .../itchat4j/demo/demo1/MyTest.java | 20 + .../itchat4j/demo/{ => demo1}/SimpleDemo.java | 38 +- .../itchat4j/demo/demo2/SimpleDemo2.java | 88 --- 20 files changed, 271 insertions(+), 909 deletions(-) delete mode 100644 src/main/java/cn/zhouyafeng/itchat4j/Wechat2.java delete mode 100644 src/main/java/cn/zhouyafeng/itchat4j/components/Login.java rename src/main/java/cn/zhouyafeng/itchat4j/{utils => core}/Core.java (96%) create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/MsgCodeEnum.java delete mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/MsgType.java create mode 100644 src/main/java/cn/zhouyafeng/itchat4j/utils/enums/RetCodeEnum.java rename src/main/java/cn/zhouyafeng/itchat4j/utils/tools/{CommonTool.java => CommonTools.java} (99%) create mode 100644 src/test/java/cn/zhouyafeng/itchat4j/demo/demo1/MyTest.java rename src/test/java/cn/zhouyafeng/itchat4j/demo/{ => demo1}/SimpleDemo.java (65%) delete mode 100644 src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java diff --git a/README.md b/README.md index 7bf22f8..2ac4d6a 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ src/main/java是itchat4j的项目源码,在src/test/java目录下有两个小D ## 消息格式 -这里简要介绍一下`msg`各种消息,msg均为`json`格式的数据,可使用各自工具进行解析,在itchat4j中我通过alibaba的`fastjosn`工具库进行了解析,每种`msg`均为`fastjson`的标准`JSONObject`对象,后续处理起来非常方便,例如获取文本消息的消息内容:`msg.getString("Text")`,获取名片消息的被推荐人昵称:`msg.getJSONObject("RecommendInfo").getString("NickName")`。有时候可能不需要处理群消息,因此在构造`msg`消息体里我添加了一个判断是否群消息的字段`groupMsg`,可通过`msg.getBooleanValue("groupMsg")`获取字段的值,如果是群消息,返回true,如果非群消息,返回false。 +这里简要介绍一下`msg`各种消息,msg均为`json`格式的数据,可使用各自工具进行解析,在itchat4j中我通过alibaba的`fastjosn`工具库进行了解析,每种`msg`均为`fastjson`的标准`JSONObject`对象,后续处理起来非常方便,例如获取文本消息的消息内容:`msg.getString("Text")`,获取名片消息的被推荐人昵称:`msg.getJSONObject("RecommendInfo").getString("NickName")`。有时候可能不需要处理群消息,因此在构造`msg`消息体里我添加了一个判断是否群消息的字段`groupMsg`,可通过`msg.getBoolean("groupMsg")`获取字段的值,如果是群消息,返回true,如果非群消息,返回false。 ### 1.文本消息 @@ -458,43 +458,55 @@ public class MsgHandler implements IMsgHandlerFace { * 简单示例程序,收到文本信息自动回复原信息,收到图片、语音、小视频后根据路径自动保存 * * @author https://github.com/yaphone - * @date 创建时间:2017年4月28日 下午10:50:36 + * @date 创建时间:2017年4月25日 上午12:18:09 * @version 1.0 * */ public class SimpleDemo implements IMsgHandlerFace { + Logger LOG = Logger.getLogger(SimpleDemo.class); @Override public String textMsgHandle(JSONObject msg) { - String text = msg.getString("Text"); - return text; + String docFilePath = "D:/itchat4j/pic/test.docx"; // 这里是需要发送的文件的路径 + if (!msg.getBoolean("groupMsg")) { // 群消息不处理 + String userId = msg.getString("FromUserName"); + MessageTools.sendFileMsgByUserId(userId, docFilePath); // 发送文件 + String text = msg.getString("Text"); // 发送文本消息,也可调用MessageTools.sendFileMsgByUserId(userId,text); + return text; + } + return null; } @Override public String picMsgHandle(JSONObject msg) { - String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + ".jpg"; // 这里使用收到图片的时间作为文件名 - String picPath = "D://itchat4j/pic" + File.separator + fileName; // 保存图片的路径 - DownloadTools.getDownloadFn(msg, MsgType.PIC, picPath); // 调用此方法来保存图片 + String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());// 这里使用收到图片的时间作为文件名 + String picPath = "D://itchat4j/pic" + File.separator + fileName + ".jpg"; // 调用此方法来保存图片 + DownloadTools.getDownloadFn(msg, MsgTypeEnum.PIC.getType(), picPath); // 保存图片的路径 return "图片保存成功"; } @Override public String voiceMsgHandle(JSONObject msg) { - String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + ".mp3"; // 这里使用收到语音的时间作为文件名 - String voicePath = "D://itchat4j/voice" + File.separator + fileName; // 保存语音的路径 - DownloadTools.getDownloadFn(msg, MsgType.VOICE, voicePath); // 调用此方法来保存语音 + String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String voicePath = "D://itchat4j/voice" + File.separator + fileName + ".mp3"; + DownloadTools.getDownloadFn(msg, MsgTypeEnum.VOICE.getType(), voicePath); return "声音保存成功"; } @Override public String viedoMsgHandle(JSONObject msg) { System.out.println(msg); - String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + ".mp4"; // 这里使用收到小视频的时间作为文件名 - String viedoPath = "D://itchat4j/viedo" + File.separator + fileName;// 保存小视频的路径 - DownloadTools.getDownloadFn(msg, MsgType.VIEDO, viedoPath);// 调用此方法来保存小视频 + String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String viedoPath = "D://itchat4j/viedo" + File.separator + fileName + ".mp4"; + DownloadTools.getDownloadFn(msg, MsgTypeEnum.VIEDO.getType(), viedoPath); return "视频保存成功"; } + @Override + public String nameCardMsgHandle(JSONObject msg) { + return "收到名片消息"; + } + } ``` @@ -510,7 +522,7 @@ public class SimpleDemo implements IMsgHandlerFace { * @version 1.0 * */ -public class Mytest { +public class MyTest { public static void main(String[] args) { String qrPath = "D://itchat4j//login"; // 保存登陆二维码图片的路径 IMsgHandlerFace msgHandler = new SimpleDemo(); // 实现IMsgHandlerFace接口的类 @@ -518,6 +530,7 @@ public class Mytest { wechat.start(); // 启动服务,会在qrPath下生成一张二维码图片,扫描即可登陆,注意,二维码图片如果超过一定时间未扫描会过期,过期时会自动更新,所以你可能需要重新打开图片 } } + ``` ### Demo2 图灵机器人 @@ -527,6 +540,7 @@ public class Mytest { 这个示例中我们接入图灵机器人的API,将收到的好友的文本信息发送给图灵机器人,并将机器人回复的消息发送给好友,接下来还是把舞台交代码和注释君吧。 ```Java + /** * 图灵机器人示例 * @@ -536,8 +550,7 @@ public class Mytest { * */ public class TulingRobot implements IMsgHandlerFace { - - MyHttpClient myHttpClient = new MyHttpClient(); + MyHttpClient myHttpClient = Core.getInstance().getMyHttpClient(); String apiKey = "597b34bea4ec4c85a775c469c84b6817"; // 这里是我申请的图灵机器人API接口,每天只能5000次调用,建议自己去申请一个,免费的:) Logger logger = Logger.getLogger("TulingRobot"); @@ -568,29 +581,39 @@ public class TulingRobot implements IMsgHandlerFace { @Override public String picMsgHandle(JSONObject msg) { - return "收到图片"; } @Override public String voiceMsgHandle(JSONObject msg) { - + String fileName = String.valueOf(new Date().getTime()); + String voicePath = "D://itchat4j/voice" + File.separator + fileName + ".mp3"; + DownloadTools.getDownloadFn(msg, MsgTypeEnum.VOICE.getType(), voicePath); return "收到语音"; } @Override public String viedoMsgHandle(JSONObject msg) { - + String fileName = String.valueOf(new Date().getTime()); + String viedoPath = "D://itchat4j/viedo" + File.separator + fileName + ".mp4"; + DownloadTools.getDownloadFn(msg, MsgTypeEnum.VIEDO.getType(), viedoPath); return "收到视频"; } public static void main(String[] args) { IMsgHandlerFace msgHandler = new TulingRobot(); - Wechat wechat = new Wechat(msgHandler, "/home/itchat4j/demo/itchat4j/login"); + Wechat wechat = new Wechat(msgHandler, "D://itchat4j/login"); wechat.start(); } + @Override + public String nameCardMsgHandle(JSONObject msg) { + // TODO Auto-generated method stub + return null; + } + } + ``` ### Demo3 itchat4j集成在SpringMVC应用中 diff --git a/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java b/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java index c8697cd..baf4ee2 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/Wechat.java @@ -1,82 +1,31 @@ package cn.zhouyafeng.itchat4j; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import com.alibaba.fastjson.JSONObject; - -import cn.zhouyafeng.itchat4j.api.MessageTools; +import cn.zhouyafeng.itchat4j.controller.LoginController; +import cn.zhouyafeng.itchat4j.core.MsgCenter; import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; -import cn.zhouyafeng.itchat4j.service.ILoginService; -import cn.zhouyafeng.itchat4j.service.impl.LoginServiceImpl; -import cn.zhouyafeng.itchat4j.utils.Core; -import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; -/** - * 主类,初始化工作 - * - * @author https://github.com/yaphone - * @date 创建时间:2017年4月25日 上午12:42:54 - * @version 1.0 - * - */ public class Wechat { - private static Logger logger = Logger.getLogger("Wechat"); - private static Core core = Core.getInstance(); - + private static final Logger LOG = LoggerFactory.getLogger(Wechat.class); private IMsgHandlerFace msgHandler; public Wechat(IMsgHandlerFace msgHandler, String qrPath) { System.setProperty("jsse.enableSNIExtension", "false"); // 防止SSL错误 - this.msgHandler = msgHandler; - // Login login = new Login(); - ILoginService login = new LoginServiceImpl(); - login.login(); - }; + + // 登陆 + LoginController login = new LoginController(); + login.login(qrPath); + } public void start() { + LOG.info("+++++++++++++++++++开始消息处理+++++++++++++++++++++"); new Thread(new Runnable() { - @Override public void run() { - while (true) { - if (core.getMsgList().size() > 0 && core.getMsgList().get(0).getString("Content") != null) { - // System.out.println(core.getMsgList().get(0)); - if (core.getMsgList().get(0).getString("Content").length() > 0) { - JSONObject msg = core.getMsgList().get(0); - if (msg.getString("Type") != null) { - if (msg.getString("Type").equals(MsgTypeEnum.TEXT.getType())) { - String result = msgHandler.textMsgHandle(msg); - MessageTools.sendMsgById(result, - core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgTypeEnum.PIC.getType())) { - String result = msgHandler.picMsgHandle(msg); - MessageTools.sendMsgById(result, - core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgTypeEnum.VOICE.getType())) { - String result = msgHandler.voiceMsgHandle(msg); - MessageTools.sendMsgById(result, - core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgTypeEnum.VIEDO.getType())) { - String result = msgHandler.viedoMsgHandle(msg); - MessageTools.sendMsgById(result, - core.getMsgList().get(0).getString("FromUserName")); - } else if (msg.getString("Type").equals(MsgTypeEnum.NAMECARD.getType())) { - String result = msgHandler.nameCardMsgHandle(msg); - MessageTools.sendMsgById(result, - core.getMsgList().get(0).getString("FromUserName")); - } - } - } - core.getMsgList().remove(0); - } - try { - TimeUnit.MILLISECONDS.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + MsgCenter.handleMsg(msgHandler); } }).start(); } diff --git a/src/main/java/cn/zhouyafeng/itchat4j/Wechat2.java b/src/main/java/cn/zhouyafeng/itchat4j/Wechat2.java deleted file mode 100644 index 41dfd46..0000000 --- a/src/main/java/cn/zhouyafeng/itchat4j/Wechat2.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.zhouyafeng.itchat4j; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import cn.zhouyafeng.itchat4j.controller.LoginController; -import cn.zhouyafeng.itchat4j.core.MsgCenter; -import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; - -public class Wechat2 { - private static final Logger LOG = LoggerFactory.getLogger(Wechat2.class); - private IMsgHandlerFace msgHandler; - - public Wechat2(IMsgHandlerFace msgHandler, String qrPath) { - System.setProperty("jsse.enableSNIExtension", "false"); // 防止SSL错误 - this.msgHandler = msgHandler; - - // 登陆 - LoginController login = new LoginController(); - login.login(qrPath); - } - - public void start() { - LOG.info("+++++++++++++++++++开始消息处理+++++++++++++++++++++"); - new Thread(new Runnable() { - @Override - public void run() { - MsgCenter.handleMsg(msgHandler); - } - }).start(); - } - -} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java b/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java index 6aef96a..8cf126d 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java @@ -6,7 +6,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Random; -import java.util.logging.Logger; import javax.activation.MimetypesFileTypeMap; @@ -16,12 +15,14 @@ import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import cn.zhouyafeng.itchat4j.core.Core; import cn.zhouyafeng.itchat4j.utils.Config; -import cn.zhouyafeng.itchat4j.utils.Core; import cn.zhouyafeng.itchat4j.utils.MyHttpClient; import cn.zhouyafeng.itchat4j.utils.enums.URLEnum; @@ -34,7 +35,7 @@ * */ public class MessageTools { - private static Logger logger = Logger.getLogger("Message"); + private static Logger LOG = LoggerFactory.getLogger(MessageTools.class); private static Core core = Core.getInstance(); private static MyHttpClient myHttpClient = core.getMyHttpClient(); @@ -47,7 +48,7 @@ public class MessageTools { * @param toUserName */ private static void sendMsg(String text, String toUserName) { - logger.info(String.format("Request to send a text message to %s: %s", toUserName, text)); + LOG.info(String.format("发送消息 %s: %s", toUserName, text)); webWxSendMsg(1, text, toUserName); } @@ -109,7 +110,7 @@ public static void webWxSendMsg(int msgType, String content, String toUserName) HttpEntity entity = myHttpClient.doPost(url, paramStr); EntityUtils.toString(entity, Consts.UTF_8); } catch (Exception e) { - logger.info(e.getMessage()); + LOG.error("webWxSendMsg", e); } } @@ -133,7 +134,7 @@ public static void webWxSendMsg(int msgType, String content, String toUserName) private static JSONObject webWxUploadMedia(String filePath) { File f = new File(filePath); if (!f.exists() && f.isFile()) { - logger.info("file is not exist"); + LOG.info("file is not exist"); return null; } String url = String.format(URLEnum.WEB_WX_UPLOAD_MEDIA.getUrl(), core.getLoginInfo().get("fileUrl")); @@ -151,7 +152,7 @@ private static JSONObject webWxUploadMedia(String filePath) { + String.valueOf(new Random().nextLong()).substring(0, 4); String webwxDataTicket = MyHttpClient.getCookie("webwx_data_ticket"); if (webwxDataTicket == null) { - logger.info("get cookie webwx_data_ticket error"); + LOG.error("get cookie webwx_data_ticket error"); return null; } @@ -183,7 +184,7 @@ private static JSONObject webWxUploadMedia(String filePath) { String result = EntityUtils.toString(entity, Consts.UTF_8); return JSON.parseObject(result); } catch (Exception e) { - logger.info(e.getMessage()); + LOG.error("webWxUploadMedia 错误: ", e); } } @@ -258,7 +259,7 @@ private static boolean webWxSendMsgImg(String userId, String mediaId) { String result = EntityUtils.toString(entity, Consts.UTF_8); return JSON.parseObject(result).getJSONObject("BaseResponse").getInteger("Ret") == 0; } catch (Exception e) { - logger.info(e.getMessage()); + LOG.error("webWxSendMsgImg 错误: ", e); } } return false; @@ -288,7 +289,7 @@ public static boolean sendFileMsgByUserId(String userId, String filePath) { data.put("totallen", responseObj.getString("StartPos")); data.put("attachid", responseObj.getString("MediaId")); } else { - logger.info("sednFileMsgByUserId error"); + LOG.error("sednFileMsgByUserId 错误: ", data); } return webWxSendAppMsg(userId, data); } @@ -354,7 +355,7 @@ private static boolean webWxSendAppMsg(String userId, Map data) String result = EntityUtils.toString(entity, Consts.UTF_8); return JSON.parseObject(result).getJSONObject("BaseResponse").getInteger("Ret") == 0; } catch (Exception e) { - logger.info(e.getMessage()); + LOG.error("错误: ", e); } } return false; diff --git a/src/main/java/cn/zhouyafeng/itchat4j/api/WechatTools.java b/src/main/java/cn/zhouyafeng/itchat4j/api/WechatTools.java index 7505e82..04db7e8 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/api/WechatTools.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/api/WechatTools.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONObject; -import cn.zhouyafeng.itchat4j.utils.Core; +import cn.zhouyafeng.itchat4j.core.Core; /** * 微信小工具,如获好友列表等 diff --git a/src/main/java/cn/zhouyafeng/itchat4j/components/Login.java b/src/main/java/cn/zhouyafeng/itchat4j/components/Login.java deleted file mode 100644 index e5da21d..0000000 --- a/src/main/java/cn/zhouyafeng/itchat4j/components/Login.java +++ /dev/null @@ -1,584 +0,0 @@ -package cn.zhouyafeng.itchat4j.components; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Random; -import java.util.logging.Logger; -import java.util.regex.Matcher; - -import org.apache.http.HttpEntity; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.util.EntityUtils; -import org.w3c.dom.Document; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; - -import cn.zhouyafeng.itchat4j.core.MsgCenter; -import cn.zhouyafeng.itchat4j.utils.Config; -import cn.zhouyafeng.itchat4j.utils.Core; -import cn.zhouyafeng.itchat4j.utils.MyHttpClient; -import cn.zhouyafeng.itchat4j.utils.tools.CommonTool; - -public class Login { - private static Logger logger = Logger.getLogger("Wechat"); - private String baseUrl = Config.BASE_URL; - private boolean isLoginIn = false; - - private Core core = Core.getInstance(); - - private MyHttpClient myHttpClient = core.getMyHttpClient(); - - public Login() { - - } - - /** - * 登陆 - * - * @author https://github.com/yaphone - * @date 2017年5月5日 上午12:04:35 - * @param qrPath - * @return - */ - public int login(String qrPath) { - if (core.isAlive()) { // 已登陆 - logger.warning("itchat has already logged in."); - return 0; - } - while (true) { - for (int count = 0; count < 10; count++) { - logger.info("Getting uuid of QR code."); - while (getQRuuid() == null) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - logger.info(e.getMessage()); - } - } - logger.info("Downloading QR code."); - Boolean qrStarge = getQR(qrPath); - if (qrStarge) { // 获取登陆二维码图片成功 - logger.info("Get QR success"); - break; - } else if (count == 10) { - logger.info("Failed to get QR code, please restart the program."); - System.exit(0); - } - } - logger.info("Please scan the QR code to log in."); - while (!isLoginIn) { - String status = checkLogin(); - if (status.equals("200")) { - isLoginIn = true; - logger.info(("登陆成功")); - } else if (status.equals("201")) { - logger.info("Please press confirm on your phone."); - isLoginIn = false; - } else { - break; - } - } - if (isLoginIn) - break; - logger.info("Log in time out, reloading QR code"); - } - this.webInit(); - this.showMobileLogin(); - CommonTool.clearScreen(); - logger.info(String.format("Login successfully as %s", core.getNickName())); - startReceiving(); - webWxGetContact(); - return 0; - } - - /** - * 生成UUID - * - * @author https://github.com/yaphone - * @date 2017年4月11日 上午12:51:29 - * @return - */ - public String getQRuuid() { - String result = null; - String uuidUrl = baseUrl + "/jslogin"; - List params = new ArrayList(); - params.add(new BasicNameValuePair("appid", "wx782c26e4c19acffb")); - params.add(new BasicNameValuePair("fun", "new")); - HttpEntity entity = myHttpClient.doGet(uuidUrl, params, true, null); - try { - result = EntityUtils.toString(entity); - } catch (Exception e) { - logger.info(e.getMessage()); - } - String regEx = "window.QRLogin.code = (\\d+); window.QRLogin.uuid = \"(\\S+?)\";"; - Matcher matcher = CommonTool.getMatcher(regEx, result); - if (matcher.find()) { - if ((matcher.group(1).equals("200"))) { - core.setUuid(matcher.group(2));// - } - } - return core.getUuid(); - } - - /** - * 获取登陆二维码图片 - * - * @author https://github.com/yaphone - * @date 2017年4月20日 下午11:44:08 - * @return - */ - public boolean getQR(String qrPath) { - // String qrPath = Config.getLocalPath() + File.separator + "QR.jpg"; - qrPath = qrPath + File.separator + "QR.jpg"; - String qrUrl = baseUrl + "/qrcode/" + core.getUuid(); - HttpEntity entity = myHttpClient.doGet(qrUrl, null, true, null); - try { - OutputStream out = new FileOutputStream(qrPath); - byte[] bytes = EntityUtils.toByteArray(entity); - out.write(bytes); - out.flush(); - out.close(); - try { - CommonTool.printQr(qrPath); // 打开登陆二维码图片 - } catch (Exception e) { - logger.info(e.getMessage()); - } - - } catch (Exception e) { - logger.info(e.getMessage()); - return false; - } - - return true; - } - - /** - * 检查登陆状态 - * - * @author https://github.com/yaphone - * @date 2017年4月8日 下午11:22:16 - * @return - */ - public String checkLogin() { - String result = ""; - String checkUrl = baseUrl + "/cgi-bin/mmwebwx-bin/login"; - Long localTime = new Date().getTime(); - List params = new ArrayList(); - params.add(new BasicNameValuePair("loginicon", "true")); - params.add(new BasicNameValuePair("uuid", core.getUuid())); - params.add(new BasicNameValuePair("tip", "0")); - params.add(new BasicNameValuePair("r", String.valueOf(localTime / 1579L))); - params.add(new BasicNameValuePair("_", String.valueOf(localTime))); - HttpEntity entity = myHttpClient.doGet(checkUrl, params, true, null); - try { - result = EntityUtils.toString(entity); - } catch (Exception e) { - logger.info(e.getMessage()); - } - String regEx = "window.code=(\\d+)"; - Matcher matcher = CommonTool.getMatcher(regEx, result); - if (matcher.find()) { - if (matcher.group(1).equals("200")) { // 已登陆 - processLoginInfo(result); - return "200"; - } else if (matcher.group(1).equals("201")) { // 已扫描,未登陆 - return "201"; - } - } - return "400"; - } - - /** - * 处理登陆信息 - * - * @author https://github.com/yaphone - * @date 2017年4月9日 下午12:16:26 - * @param result - */ - public void processLoginInfo(String loginContent) { - String regEx = "window.redirect_uri=\"(\\S+)\";"; - Matcher matcher = CommonTool.getMatcher(regEx, loginContent); - if (matcher.find()) { - String originalUrl = matcher.group(1); - String url = originalUrl.substring(0, originalUrl.lastIndexOf('/')); // https://wx2.qq.com/cgi-bin/mmwebwx-bin - core.getLoginInfo().put("url", url); - Map> possibleUrlMap = getPossibleUrlMap(); - Iterator>> iterator = possibleUrlMap.entrySet().iterator(); - Map.Entry> entry; - String fileUrl; - String syncUrl; - while (iterator.hasNext()) { - entry = iterator.next(); - String indexUrl = entry.getKey(); - fileUrl = "https://" + entry.getValue().get(0) + "/cgi-bin/mmwebwx-bin"; - syncUrl = "https://" + entry.getValue().get(1) + "/cgi-bin/mmwebwx-bin"; - if (core.getLoginInfo().get("url").toString().contains(indexUrl)) { - core.getLoginInfo().put("fileUrl", fileUrl); - core.getLoginInfo().put("syncUrl", syncUrl); - break; - } - } - if (core.getLoginInfo().get("fileUrl") == null && core.getLoginInfo().get("syncUrl") == null) { - core.getLoginInfo().put("fileUrl", url); - core.getLoginInfo().put("syncUrl", url); - } - core.getLoginInfo().put("deviceid", "e" + String.valueOf(new Random().nextLong()).substring(1, 16)); // 生成15位随机数 - core.getLoginInfo().put("BaseRequest", new ArrayList()); - String text = ""; - // // 禁止重定向 - - try { - HttpEntity entity = myHttpClient.doGet(originalUrl, null, false, null); - text = EntityUtils.toString(entity); - } catch (Exception e) { - logger.info(e.getMessage()); - return; - } - Document doc = CommonTool.xmlParser(text); - Map> BaseRequest = new HashMap>(); - Map baseRequest = new HashMap(); - if (doc != null) { - core.getLoginInfo().put("skey", - doc.getElementsByTagName("skey").item(0).getFirstChild().getNodeValue()); - baseRequest.put("Skey", (String) core.getLoginInfo().get("skey")); - core.getLoginInfo().put("wxsid", - doc.getElementsByTagName("wxsid").item(0).getFirstChild().getNodeValue()); - baseRequest.put("Sid", (String) core.getLoginInfo().get("wxsid")); - core.getLoginInfo().put("wxuin", - doc.getElementsByTagName("wxuin").item(0).getFirstChild().getNodeValue()); - baseRequest.put("Uin", (String) core.getLoginInfo().get("wxuin")); - core.getLoginInfo().put("pass_ticket", - doc.getElementsByTagName("pass_ticket").item(0).getFirstChild().getNodeValue()); - baseRequest.put("DeviceID", (String) core.getLoginInfo().get("deviceid")); - BaseRequest.put("BaseRequest", baseRequest); - core.getLoginInfo().put("baseRequest", BaseRequest); - } - - } - } - - Map> getPossibleUrlMap() { - Map> possibleUrlMap = new HashMap>(); - possibleUrlMap.put("wx2.qq.com", new ArrayList() { - /** - * - */ - private static final long serialVersionUID = 1L; - - { - add("file.wx2.qq.com"); - add("webpush.wx2.qq.com"); - } - }); - possibleUrlMap.put("wx8.qq.com", new ArrayList() { - /** - * - */ - private static final long serialVersionUID = 1L; - - { - add("file.wx8.qq.com"); - add("webpush.wx8.qq.com"); - } - }); - - possibleUrlMap.put("web2.wechat.com", new ArrayList() { - /** - * - */ - private static final long serialVersionUID = 1L; - - { - add("file.web2.wechat.com"); - add("webpush.web2.wechat.com"); - } - }); - possibleUrlMap.put("wechat.com", new ArrayList() { - /** - * - */ - private static final long serialVersionUID = 1L; - - { - add("file.web.wechat.com"); - add("webpush.web.wechat.com"); - } - }); - return possibleUrlMap; - } - - private JSONObject webInit() { - JSONObject obj = null; - String url = core.getLoginInfo().get("url") + "/webwxinit?&r=" + String.valueOf(new Date().getTime()); - @SuppressWarnings("unchecked") - Map> paramMap = (Map>) core.getLoginInfo() - .get("baseRequest"); - String paramStr = JSON.toJSONString(paramMap); - try { - HttpEntity entity = myHttpClient.doPost(url, paramStr); - String result = EntityUtils.toString(entity, "UTF-8"); - obj = JSON.parseObject(result); - // TODO utils.emoji_formatter(dic['User'], 'NickName') - core.getLoginInfo().put("InviteStartCount", obj.getInteger("InviteStartCount")); - core.getLoginInfo().put("User", CommonTool.structFriendInfo(obj.getJSONObject("User"))); // 为userObj添加新字段 - core.getLoginInfo().put("SyncKey", obj.getJSONObject("SyncKey")); - JSONArray syncArray = obj.getJSONObject("SyncKey").getJSONArray("List"); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < syncArray.size(); i++) { - sb.append(syncArray.getJSONObject(i).getString("Key") + "_" - + syncArray.getJSONObject(i).getString("Val") + "|"); - } - String synckey = sb.toString(); - core.getLoginInfo().put("synckey", synckey.substring(0, synckey.length() - 1));// 1_656161336|2_656161626|3_656161313|11_656159955|13_656120033|201_1492273724|1000_1492265953|1001_1492250432|1004_1491805192 - core.setUserName((obj.getJSONObject("User")).getString("UserName")); - core.setNickName((obj.getJSONObject("User")).getString("NickName")); - core.setUserSelf(obj.getJSONObject("User")); - } catch (Exception e) { - e.printStackTrace(); - } - return obj; - } - - private void showMobileLogin() { - String url = (String) core.getLoginInfo().get("url"); - String passTicket = (String) core.getLoginInfo().get("pass_ticket"); - String mobileUrl = String.format("%s/webwxstatusnotify?lang=zh_CN&pass_ticket=%s", url, passTicket); - Map paramMap = new HashMap(); - @SuppressWarnings("unchecked") - Map> baseRequestMap = (Map>) core.getLoginInfo() - .get("baseRequest"); - paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest")); - paramMap.put("Code", 3); - paramMap.put("FromUserName", core.getUserName()); - paramMap.put("ToUserName", core.getUserName()); - paramMap.put("ClientMsgId", String.valueOf(new Date().getTime())); - String paramStr = JSON.toJSONString(paramMap); - try { - HttpEntity entity = myHttpClient.doPost(mobileUrl, paramStr); - EntityUtils.toString(entity, "UTF-8"); - } catch (Exception e) { - - } - } - - void startReceiving() { - core.setAlive(true); - new Thread(new Runnable() { - int retryCount = 0; - - @Override - public void run() { - while (core.isAlive()) { - try { - Map resultMap = syncCheck(); - String retcode = resultMap.get("retcode"); - String selector = resultMap.get("selector"); - if (retcode.equals("9999")) { - continue; - } else if (retcode.equals("1100")) { // 退出 - logger.info("login out"); - break; - } else if (retcode.equals("1101")) { // 其它地方登陆 - logger.info("login otherwhere"); - break; - } else if (retcode.equals("1102")) { // 移动端退出 - logger.info("login quit on phone"); - break; - } else if (retcode.equals("0")) { - if (selector.equals("2")) { - JSONObject msgObj = webWxSync(); - if (msgObj != null) { - try { - JSONArray msgList = new JSONArray(); - msgList = msgObj.getJSONArray("AddMsgList"); - msgList = MsgCenter.produceMsg(msgList); - for (int j = 0; j < msgList.size(); j++) { - core.getMsgList().add(msgList.getJSONObject(j)); - } - } catch (Exception e) { - logger.info(e.getMessage()); - } - } else if (selector.equals("7")) { - webWxSync(); - } else if (selector.equals("4")) { - // 保存群聊到通讯录 - // 修改群名称 - // 新增或删除联系人 - // 群聊成员数目变化 - // TODO - } else if (selector.equals("3") || selector.equals("6")) { - break; - } - } - } else { - JSONObject obj = webWxSync(); - logger.info(obj.toJSONString()); - } - } catch (Exception e) { - logger.info(e.getMessage()); - retryCount += 1; - if (core.getReceivingRetryCount() < retryCount) { - core.setAlive(false); - } else { - try { - Thread.sleep(1000); - } catch (InterruptedException e1) { - logger.info(e.getMessage()); - } - } - } - - } - } - }).start(); - } - - /** - * 检查是否有新消息 check whether there's a message - * - * @author https://github.com/yaphone - * @date 2017年4月16日 上午11:11:34 - * @return - * - */ - private Map syncCheck() { - Map resultMap = new HashMap(); - String syncUrl = (String) core.getLoginInfo().get("syncUrl"); - // String syncUrl = "https://webpush.wx2.qq.com/cgi-bin/mmwebwx-bin"; - if (syncUrl == null || syncUrl.equals("")) { - syncUrl = (String) core.getLoginInfo().get("url"); - } - String url = String.format("%s/synccheck", syncUrl); - List params = new ArrayList(); - params.add(new BasicNameValuePair("r", String.valueOf(new Date().getTime()))); - params.add(new BasicNameValuePair("skey", (String) core.getLoginInfo().get("skey"))); - params.add(new BasicNameValuePair("sid", (String) core.getLoginInfo().get("wxsid"))); - params.add(new BasicNameValuePair("uin", (String) core.getLoginInfo().get("wxuin"))); - params.add(new BasicNameValuePair("deviceid", (String) core.getLoginInfo().get("deviceid"))); - params.add(new BasicNameValuePair("synckey", (String) core.getLoginInfo().get("synckey"))); - params.add(new BasicNameValuePair("_", String.valueOf(new Date().getTime()))); - try { - HttpEntity entity = myHttpClient.doGet(url, params, true, null); - if (entity == null) { - resultMap.put("retcode", "9999"); - resultMap.put("selector", "9999"); - return resultMap; - } - String text = EntityUtils.toString(entity); - String regEx = "window.synccheck=\\{retcode:\"(\\d+)\",selector:\"(\\d+)\"\\}"; - Matcher matcher = CommonTool.getMatcher(regEx, text); - if (!matcher.find() || matcher.group(1).equals("2")) { - logger.info(String.format("Unexpected sync check result: %s", text)); - } else { - resultMap.put("retcode", matcher.group(1)); - resultMap.put("selector", matcher.group(2)); - } - } catch (Exception e) { - e.printStackTrace(); - } - return resultMap; - } - - /** - * 同步消息 sync the messages - * - * @author https://github.com/yaphone - * @date 2017年5月12日 上午12:24:55 - * @return - */ - JSONObject webWxSync() { - JSONObject result = null; - String url = String.format("%s/webwxsync?sid=%s&skey=%s&pass_ticket=%s", core.getLoginInfo().get("url"), - core.getLoginInfo().get("wxsid"), core.getLoginInfo().get("skey"), - core.getLoginInfo().get("pass_ticket")); - Map paramMap = new HashMap(); - @SuppressWarnings("unchecked") - Map> baseRequestMap = (Map>) core.getLoginInfo() - .get("baseRequest"); - paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest")); - paramMap.put("SyncKey", core.getLoginInfo().get("SyncKey")); - paramMap.put("rr", -new Date().getTime() / 1000); - String paramStr = JSON.toJSONString(paramMap); - try { - HttpEntity entity = myHttpClient.doPost(url, paramStr); - String text = EntityUtils.toString(entity, "UTF-8"); - JSONObject obj = JSON.parseObject(text); - if (obj.getJSONObject("BaseResponse").getInteger("Ret") != 0) { - result = null; - } else { - result = obj; - core.getLoginInfo().put("SyncKey", obj.getJSONObject("SyncCheckKey")); - JSONArray syncArray = obj.getJSONObject("SyncKey").getJSONArray("List"); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < syncArray.size(); i++) { - sb.append(syncArray.getJSONObject(i).getString("Key") + "_" - + syncArray.getJSONObject(i).getString("Val") + "|"); - } - String synckey = sb.toString(); - core.getLoginInfo().put("synckey", synckey.substring(0, synckey.length() - 1));// 1_656161336|2_656161626|3_656161313|11_656159955|13_656120033|201_1492273724|1000_1492265953|1001_1492250432|1004_1491805192 - } - } catch (Exception e) { - logger.info(e.getMessage()); - } - return result; - - } - - /** - *

- * 获取联系人信息,成功返回true,失败返回false - *

- *

- * get all contacts: people, group, public user, special user - *

- * - * @author https://github.com/yaphone - * @date 2017年5月3日 上午12:28:51 - * @return - */ - boolean webWxGetContact() { - String result = ""; - String url = String.format("%s/webwxgetcontact", core.getLoginInfo().get("url")); - List params = new ArrayList(); - params.add(new BasicNameValuePair("pass_ticket", (String) core.getLoginInfo().get("pass_ticket"))); - params.add(new BasicNameValuePair("skey", (String) core.getLoginInfo().get("skey"))); - params.add(new BasicNameValuePair("r", String.valueOf(String.valueOf(new Date().getTime())))); - HttpEntity entity = myHttpClient.doGet(url, params, true, null); - try { - result = EntityUtils.toString(entity, "UTF-8"); - } catch (Exception e) { - logger.info(e.getMessage()); - } - JSONObject fullFriendsJsonList = JSON.parseObject(result); - core.setMemberCount(fullFriendsJsonList.getInteger(("MemberCount"))); - JSONArray memberJsonArray = fullFriendsJsonList.getJSONArray("MemberList"); - for (int i = 0; i < memberJsonArray.size(); i++) { - core.getMemberList().add(memberJsonArray.getJSONObject(i)); - } - for (JSONObject o : core.getMemberList()) { - if ((o.getInteger("VerifyFlag") & 8) != 0) { // 公众号/服务号 - core.getPublicUsersList().add(o); - } else if (Config.API_SPECIAL_USER.contains(o.getString("UserName"))) { // 特殊账号 - core.getSpecialUsersList().add(o); - } else if (o.getString("UserName").indexOf("@@") != -1) { // 群聊 - core.getGroupList().add(o); - } else if (o.getString("UserName").equals(core.getUserSelf().getString("UserName"))) { // 自己 - core.getContactList().remove(o); - } else { // 普通联系人 - core.getContactList().add(o); - } - } - return true; - } - -} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/controller/LoginController.java b/src/main/java/cn/zhouyafeng/itchat4j/controller/LoginController.java index 60ab1df..2d5fce9 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/controller/LoginController.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/controller/LoginController.java @@ -3,11 +3,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import cn.zhouyafeng.itchat4j.core.Core; import cn.zhouyafeng.itchat4j.service.ILoginService; import cn.zhouyafeng.itchat4j.service.impl.LoginServiceImpl; -import cn.zhouyafeng.itchat4j.utils.Core; import cn.zhouyafeng.itchat4j.utils.SleepUtils; -import cn.zhouyafeng.itchat4j.utils.tools.CommonTool; +import cn.zhouyafeng.itchat4j.utils.tools.CommonTools; /** * 登陆控制器 @@ -65,7 +65,7 @@ public void login(String qrPath) { loginService.wxStatusNotify(); LOG.info("6. 清除。。。。"); - CommonTool.clearScreen(); + CommonTools.clearScreen(); LOG.info(String.format("欢迎回来, %s", core.getNickName())); LOG.info("7. 开始接收消息"); diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java b/src/main/java/cn/zhouyafeng/itchat4j/core/Core.java similarity index 96% rename from src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java rename to src/main/java/cn/zhouyafeng/itchat4j/core/Core.java index 6455de5..b428f12 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/core/Core.java @@ -1,4 +1,4 @@ -package cn.zhouyafeng.itchat4j.utils; +package cn.zhouyafeng.itchat4j.core; import java.util.ArrayList; import java.util.HashMap; @@ -7,6 +7,7 @@ import com.alibaba.fastjson.JSONObject; +import cn.zhouyafeng.itchat4j.utils.MyHttpClient; import cn.zhouyafeng.itchat4j.utils.enums.parameters.BaseParaEnum; /** @@ -64,6 +65,11 @@ public static Core getInstance() { */ public Map getParamMap() { return new HashMap(1) { + /** + * + */ + private static final long serialVersionUID = 1L; + { Map map = new HashMap(); for (BaseParaEnum baseRequest : BaseParaEnum.values()) { diff --git a/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java b/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java index f5355f8..d97b338 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/core/MsgCenter.java @@ -11,11 +11,18 @@ import cn.zhouyafeng.itchat4j.api.MessageTools; import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; -import cn.zhouyafeng.itchat4j.utils.Core; -import cn.zhouyafeng.itchat4j.utils.MsgType; +import cn.zhouyafeng.itchat4j.utils.MsgCodeEnum; import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; -import cn.zhouyafeng.itchat4j.utils.tools.CommonTool; +import cn.zhouyafeng.itchat4j.utils.tools.CommonTools; +/** + * 消息处理中心 + * + * @author https://github.com/yaphone + * @date 创建时间:2017年5月14日 下午12:47:50 + * @version 1.0 + * + */ public class MsgCenter { private static Logger LOG = LoggerFactory.getLogger(MsgCenter.class); @@ -36,8 +43,6 @@ public static JSONArray produceMsg(JSONArray msgList) { JSONObject m = msgList.getJSONObject(i); m.put("groupMsg", false);// 是否是群消息 if (m.getString("FromUserName").contains("@@") || m.getString("ToUserName").contains("@@")) { // 群聊消息 - // produceGroupChat(core, m); - // m.remove("Content"); if (m.getString("FromUserName").contains("@@") && !core.getGroupIdList().contains(m.getString("FromUserName"))) { core.getGroupIdList().add((m.getString("FromUserName"))); @@ -52,12 +57,13 @@ public static JSONArray produceMsg(JSONArray msgList) { m.put("groupMsg", true); } } else { - CommonTool.msgFormatter(m, "Content"); + CommonTools.msgFormatter(m, "Content"); } - if (m.getInteger("MsgType") == MsgType.MSGTYPE_TEXT) { // words 文本消息 + if (m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_TEXT.getCode()) { // words + // 文本消息 if (m.getString("Url").length() != 0) { String regEx = "(.+?\\(.+?\\))"; - Matcher matcher = CommonTool.getMatcher(regEx, m.getString("Content")); + Matcher matcher = CommonTools.getMatcher(regEx, m.getString("Content")); String data = "Map"; if (matcher.find()) { data = matcher.group(1); @@ -65,44 +71,55 @@ public static JSONArray produceMsg(JSONArray msgList) { msg.put("Type", "Map"); msg.put("Text", data); } else { - msg.put("Type", MsgTypeEnum.TEXT); + msg.put("Type", MsgTypeEnum.TEXT.getType()); msg.put("Text", m.getString("Content")); } m.put("Type", msg.getString("Type")); m.put("Text", msg.getString("Text")); - } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_IMAGE - || m.getInteger("MsgType") == MsgType.MSGTYPE_EMOTICON) { // 图片消息 + } else if (m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_IMAGE.getCode() + || m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_EMOTICON.getCode()) { // 图片消息 m.put("Type", MsgTypeEnum.PIC.getType()); - } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_VOICE) { // 语音消息 + } else if (m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_VOICE.getCode()) { // 语音消息 m.put("Type", MsgTypeEnum.VOICE.getType()); - } else if (m.getInteger("MsgType") == 37) {// friends 好友确认消息 + } else if (m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_VERIFYMSG.getCode()) {// friends + // 好友确认消息 - } else if (m.getInteger("MsgType") == 42) { // 共享名片 + } else if (m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_SHARECARD.getCode()) { // 共享名片 m.put("Type", MsgTypeEnum.NAMECARD.getType()); - } else if (m.getInteger("MsgType") == MsgType.MSGTYPE_VIDEO - || m.getInteger("MsgType") == MsgType.MSGTYPE_MICROVIDEO) {// viedo + } else if (m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_VIDEO.getCode() + || m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_MICROVIDEO.getCode()) {// viedo m.put("Type", MsgTypeEnum.VIEDO.getType()); - } else if (m.getInteger("MsgType") == 49) { // sharing 分享链接 + } else if (m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_APP.getCode()) { // sharing + // 分享链接 - } else if (m.getInteger("MsgType") == 51) {// phone init 微信初始化消息 + } else if (m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_STATUSNOTIFY.getCode()) {// phone + // init + // 微信初始化消息 - } else if (m.getInteger("MsgType") == 10000) {// 系统消息 + } else if (m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_SYS.getCode()) {// 系统消息 - } else if (m.getInteger("MsgType") == 10002) { // 撤回消息 + } else if (m.getInteger("MsgType") == MsgCodeEnum.MSGTYPE_RECALLED.getCode()) { // 撤回消息 } else { LOG.info("Useless msg"); } + LOG.info("收到消息一条,来自: " + m.getString("FromUserName")); result.add(m); } return result; } + /** + * 消息处理 + * + * @author https://github.com/yaphone + * @date 2017年5月14日 上午10:52:34 + * @param msgHandler + */ public static void handleMsg(IMsgHandlerFace msgHandler) { while (true) { if (core.getMsgList().size() > 0 && core.getMsgList().get(0).getString("Content") != null) { - // System.out.println(core.getMsgList().get(0)); if (core.getMsgList().get(0).getString("Content").length() > 0) { JSONObject msg = core.getMsgList().get(0); if (msg.getString("Type") != null) { diff --git a/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java b/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java index 87917b2..af061a0 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/service/impl/LoginServiceImpl.java @@ -25,20 +25,21 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import cn.zhouyafeng.itchat4j.core.Core; import cn.zhouyafeng.itchat4j.core.MsgCenter; import cn.zhouyafeng.itchat4j.service.ILoginService; import cn.zhouyafeng.itchat4j.utils.Config; -import cn.zhouyafeng.itchat4j.utils.Core; import cn.zhouyafeng.itchat4j.utils.MyHttpClient; import cn.zhouyafeng.itchat4j.utils.SleepUtils; import cn.zhouyafeng.itchat4j.utils.enums.ResultEnum; +import cn.zhouyafeng.itchat4j.utils.enums.RetCodeEnum; import cn.zhouyafeng.itchat4j.utils.enums.StorageLoginInfoEnum; import cn.zhouyafeng.itchat4j.utils.enums.URLEnum; import cn.zhouyafeng.itchat4j.utils.enums.parameters.BaseParaEnum; import cn.zhouyafeng.itchat4j.utils.enums.parameters.LoginParaEnum; import cn.zhouyafeng.itchat4j.utils.enums.parameters.StatusNotifyParaEnum; import cn.zhouyafeng.itchat4j.utils.enums.parameters.UUIDParaEnum; -import cn.zhouyafeng.itchat4j.utils.tools.CommonTool; +import cn.zhouyafeng.itchat4j.utils.tools.CommonTools; /** * 登陆服务实现类 @@ -83,13 +84,11 @@ public boolean login() { String status = checklogin(result); if (ResultEnum.SUCCESS.getCode().equals(status)) { - LOG.info(("登陆成功")); processLoginInfo(result); // 处理结果 isLogin = true; core.setAlive(isLogin); break; } - if (ResultEnum.WAIT_CONFIRM.getCode().equals(status)) { LOG.info("请点击微信确认按钮,进行登陆"); } @@ -115,7 +114,7 @@ public String getUuid() { try { String result = EntityUtils.toString(entity); String regEx = "window.QRLogin.code = (\\d+); window.QRLogin.uuid = \"(\\S+?)\";"; - Matcher matcher = CommonTool.getMatcher(regEx, result); + Matcher matcher = CommonTools.getMatcher(regEx, result); if (matcher.find()) { if ((ResultEnum.SUCCESS.getCode().equals(matcher.group(1)))) { core.setUuid(matcher.group(2)); @@ -140,7 +139,7 @@ public boolean getQR(String qrPath) { out.flush(); out.close(); try { - CommonTool.printQr(qrPath); // 打开登陆二维码图片 + CommonTools.printQr(qrPath); // 打开登陆二维码图片 } catch (Exception e) { LOG.info(e.getMessage()); } @@ -169,7 +168,6 @@ public boolean webWxInit() { String result = EntityUtils.toString(entity, Consts.UTF_8); JSONObject obj = JSON.parseObject(result); - LOG.info(obj.toString());// 调试 JSONObject user = obj.getJSONObject(StorageLoginInfoEnum.User.getKey()); JSONObject syncKey = obj.getJSONObject(StorageLoginInfoEnum.SyncKey.getKey()); @@ -213,7 +211,7 @@ public void wxStatusNotify() { try { HttpEntity entity = httpClient.doPost(url, paramStr); - EntityUtils.toString(entity, Consts.UTF_8);// TODO + EntityUtils.toString(entity, Consts.UTF_8); } catch (Exception e) { LOG.error("微信状态通知接口失败!", e); } @@ -233,18 +231,19 @@ public void run() { Map resultMap = syncCheck(); String retcode = resultMap.get("retcode"); String selector = resultMap.get("selector"); - if (retcode.equals("9999")) { + if (retcode.equals(RetCodeEnum.UNKOWN.getCode())) { + LOG.info(RetCodeEnum.UNKOWN.getType()); continue; - } else if (retcode.equals("1100")) { // 退出 - LOG.info("login out"); + } else if (retcode.equals(RetCodeEnum.LOGIN_OUT.getCode())) { // 退出 + LOG.info(RetCodeEnum.LOGIN_OUT.getType()); break; - } else if (retcode.equals("1101")) { // 其它地方登陆 - LOG.info("login otherwhere"); + } else if (retcode.equals(RetCodeEnum.LOGIN_OTHERWHERE.getCode())) { // 其它地方登陆 + LOG.info(RetCodeEnum.LOGIN_OTHERWHERE.getType()); break; - } else if (retcode.equals("1102")) { // 移动端退出 - LOG.info("login quit on phone"); + } else if (retcode.equals(RetCodeEnum.MOBILE_LOGIN_OUT.getCode())) { // 移动端退出 + LOG.info(RetCodeEnum.MOBILE_LOGIN_OUT.getType()); break; - } else if (retcode.equals("0")) { + } else if (retcode.equals(RetCodeEnum.NORMAL.getCode())) { if (selector.equals("2")) { JSONObject msgObj = webWxSync(); if (msgObj != null) { @@ -272,7 +271,6 @@ public void run() { } } else { JSONObject obj = webWxSync(); - LOG.info(obj.toJSONString()); } } catch (Exception e) { LOG.info(e.getMessage()); @@ -307,7 +305,7 @@ public void webWxGetContact() { core.setMemberCount(fullFriendsJsonList.getInteger(StorageLoginInfoEnum.MemberCount.getKey())); JSONArray member = fullFriendsJsonList.getJSONArray(StorageLoginInfoEnum.MemberList.getKey()); - for (Iterator iterator = member.iterator(); iterator.hasNext();) { + for (Iterator iterator = member.iterator(); iterator.hasNext();) { JSONObject o = (JSONObject) iterator.next(); if ((o.getInteger("VerifyFlag") & 8) != 0) { // 公众号/服务号 @@ -337,7 +335,7 @@ public void webWxGetContact() { */ public String checklogin(String result) { String regEx = "window.code=(\\d+)"; - Matcher matcher = CommonTool.getMatcher(regEx, result); + Matcher matcher = CommonTools.getMatcher(regEx, result); if (matcher.find()) { return matcher.group(1); } @@ -353,7 +351,7 @@ public String checklogin(String result) { */ private void processLoginInfo(String loginContent) { String regEx = "window.redirect_uri=\"(\\S+)\";"; - Matcher matcher = CommonTool.getMatcher(regEx, loginContent); + Matcher matcher = CommonTools.getMatcher(regEx, loginContent); if (matcher.find()) { String originalUrl = matcher.group(1); String url = originalUrl.substring(0, originalUrl.lastIndexOf('/')); // https://wx2.qq.com/cgi-bin/mmwebwx-bin @@ -389,7 +387,7 @@ private void processLoginInfo(String loginContent) { LOG.info(e.getMessage()); return; } - Document doc = CommonTool.xmlParser(text); + Document doc = CommonTools.xmlParser(text); if (doc != null) { core.getLoginInfo().put(StorageLoginInfoEnum.skey.getKey(), doc.getElementsByTagName(StorageLoginInfoEnum.skey.getKey()).item(0).getFirstChild() @@ -533,7 +531,7 @@ private Map syncCheck() { } String text = EntityUtils.toString(entity); String regEx = "window.synccheck=\\{retcode:\"(\\d+)\",selector:\"(\\d+)\"\\}"; - Matcher matcher = CommonTool.getMatcher(regEx, text); + Matcher matcher = CommonTools.getMatcher(regEx, text); if (!matcher.find() || matcher.group(1).equals("2")) { LOG.info(String.format("Unexpected sync check result: %s", text)); } else { diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/MsgCodeEnum.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/MsgCodeEnum.java new file mode 100644 index 0000000..5e79710 --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/MsgCodeEnum.java @@ -0,0 +1,68 @@ +package cn.zhouyafeng.itchat4j.utils; + +/** + * 消息类型 + * + * @author https://github.com/yaphone + * @date 创建时间:2017年4月23日 下午12:15:00 + * @version 1.0 + * + */ +public enum MsgCodeEnum { + + // public static final int MSGTYPE_TEXT = 1; // 文本消息类型 + // public static final int MSGTYPE_IMAGE = 3; // 图片消息 + // public static final int MSGTYPE_VOICE = 34; // 语音消息 + // public static final int MSGTYPE_VIDEO = 43; // 小视频消息 + // public static final int MSGTYPE_MICROVIDEO = 62; // 短视频消息 + // public static final int MSGTYPE_EMOTICON = 47; // 表情消息 + // public static final int MSGTYPE_APP = 49; + // public static final int MSGTYPE_VOIPMSG = 50; + // public static final int MSGTYPE_VOIPNOTIFY = 52; + // public static final int MSGTYPE_VOIPINVITE = 53; + // public static final int MSGTYPE_LOCATION = 48; + // public static final int MSGTYPE_STATUSNOTIFY = 51; + // public static final int MSGTYPE_SYSNOTICE = 9999; + // public static final int MSGTYPE_POSSIBLEFRIEND_MSG = 40; + // public static final int MSGTYPE_VERIFYMSG = 37; + // public static final int MSGTYPE_SHARECARD = 42; + // public static final int MSGTYPE_SYS = 10000; + // public static final int MSGTYPE_RECALLED = 10002; + MSGTYPE_TEXT(1, "文本消息类型"), + MSGTYPE_IMAGE(3, "图片消息"), + MSGTYPE_VOICE(34, "语音消息"), + MSGTYPE_VIDEO(43, "小视频消息"), + MSGTYPE_MICROVIDEO(62, "短视频消息"), + MSGTYPE_EMOTICON(47, "表情消息"), + MSGTYPE_APP(49, ""), + MSGTYPE_VOIPMSG(50, ""), + MSGTYPE_VOIPNOTIFY(52, ""), + MSGTYPE_VOIPINVITE(53, ""), + MSGTYPE_LOCATION(48, ""), + MSGTYPE_STATUSNOTIFY(51, ""), + MSGTYPE_SYSNOTICE(9999, ""), + MSGTYPE_POSSIBLEFRIEND_MSG(40, ""), + MSGTYPE_VERIFYMSG(37, ""), + MSGTYPE_SHARECARD(42, ""), + MSGTYPE_SYS(10000, ""), + MSGTYPE_RECALLED(10002, "") + + ; + + private int code; + private String type; + + MsgCodeEnum(int code, String type) { + this.code = code; + this.type = type; + } + + public int getCode() { + return code; + } + + public String getType() { + return type; + } + +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/MsgType.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/MsgType.java deleted file mode 100644 index fc9da54..0000000 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/MsgType.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.zhouyafeng.itchat4j.utils; - -/** - * 消息类型 - * - * @author https://github.com/yaphone - * @date 创建时间:2017年4月23日 下午12:15:00 - * @version 1.0 - * - */ -public class MsgType { - - public static final int MSGTYPE_TEXT = 1; // 文本消息类型 - public static final int MSGTYPE_IMAGE = 3; // 图片消息 - public static final int MSGTYPE_VOICE = 34; // 语音消息 - public static final int MSGTYPE_VIDEO = 43; // 小视频消息 - public static final int MSGTYPE_MICROVIDEO = 62; - public static final int MSGTYPE_EMOTICON = 47; - public static final int MSGTYPE_APP = 49; - public static final int MSGTYPE_VOIPMSG = 50; - public static final int MSGTYPE_VOIPNOTIFY = 52; - public static final int MSGTYPE_VOIPINVITE = 53; - public static final int MSGTYPE_LOCATION = 48; - public static final int MSGTYPE_STATUSNOTIFY = 51; - public static final int MSGTYPE_SYSNOTICE = 9999; - public static final int MSGTYPE_POSSIBLEFRIEND_MSG = 40; - public static final int MSGTYPE_VERIFYMSG = 37; - public static final int MSGTYPE_SHARECARD = 42; - public static final int MSGTYPE_SYS = 10000; - public static final int MSGTYPE_RECALLED = 10002; - -} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/MyHttpClient.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/MyHttpClient.java index 431a154..06d7b90 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/MyHttpClient.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/MyHttpClient.java @@ -99,7 +99,6 @@ public HttpEntity doGet(String url, List params, boolean red if (params != null) { String paramStr = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8)); httpGet = new HttpGet(url + "?" + paramStr); - System.out.println(httpGet.getURI()); } else { httpGet = new HttpGet(url); diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/RetCodeEnum.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/RetCodeEnum.java new file mode 100644 index 0000000..97f807d --- /dev/null +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/enums/RetCodeEnum.java @@ -0,0 +1,30 @@ +package cn.zhouyafeng.itchat4j.utils.enums; + +public enum RetCodeEnum { + + NORMAL("0", "普通"), + LOGIN_OUT("1102", "退出"), + LOGIN_OTHERWHERE("1101", "其它地方登陆"), + MOBILE_LOGIN_OUT("1102", "移动端退出"), + UNKOWN("9999", "未知") + + ; + + + private String code; + private String type; + + RetCodeEnum(String code, String type) { + this.code = code; + this.type = type; + } + + public String getCode() { + return code; + } + + public String getType() { + return type; + } + +} diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/CommonTool.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/CommonTools.java similarity index 99% rename from src/main/java/cn/zhouyafeng/itchat4j/utils/tools/CommonTool.java rename to src/main/java/cn/zhouyafeng/itchat4j/utils/tools/CommonTools.java index 698e506..8e2672f 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/CommonTool.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/CommonTools.java @@ -31,7 +31,7 @@ * @version 1.0 * */ -public class CommonTool { +public class CommonTools { public static boolean printQr(String qrPath) { diff --git a/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/DownloadTools.java b/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/DownloadTools.java index 426e5b8..2ab698d 100644 --- a/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/DownloadTools.java +++ b/src/main/java/cn/zhouyafeng/itchat4j/utils/tools/DownloadTools.java @@ -14,7 +14,7 @@ import com.alibaba.fastjson.JSONObject; -import cn.zhouyafeng.itchat4j.utils.Core; +import cn.zhouyafeng.itchat4j.core.Core; import cn.zhouyafeng.itchat4j.utils.MyHttpClient; import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; import cn.zhouyafeng.itchat4j.utils.enums.URLEnum; diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java index 348abc6..1770476 100644 --- a/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/TulingRobot.java @@ -13,8 +13,8 @@ import com.alibaba.fastjson.JSONObject; import cn.zhouyafeng.itchat4j.Wechat; +import cn.zhouyafeng.itchat4j.core.Core; import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; -import cn.zhouyafeng.itchat4j.utils.Core; import cn.zhouyafeng.itchat4j.utils.MyHttpClient; import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; import cn.zhouyafeng.itchat4j.utils.tools.DownloadTools; @@ -29,7 +29,7 @@ */ public class TulingRobot implements IMsgHandlerFace { MyHttpClient myHttpClient = Core.getInstance().getMyHttpClient(); - String apiKey = "597b34bea4ec4c85a775c469c84b6817"; + String apiKey = "597b34bea4ec4c85a775c469c84b6817"; // 这里是我申请的图灵机器人API接口,每天只能5000次调用,建议自己去申请一个,免费的:) Logger logger = Logger.getLogger("TulingRobot"); @Override diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/demo1/MyTest.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/demo1/MyTest.java new file mode 100644 index 0000000..53835de --- /dev/null +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/demo1/MyTest.java @@ -0,0 +1,20 @@ +package cn.zhouyafeng.itchat4j.demo.demo1; + +import cn.zhouyafeng.itchat4j.Wechat; +import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; + +/** + * + * @author https://github.com/yaphone + * @date 创建时间:2017年4月28日 上午12:44:10 + * @version 1.0 + * + */ +public class MyTest { + public static void main(String[] args) { + String qrPath = "D://itchat4j//login"; // 保存登陆二维码图片的路径 + IMsgHandlerFace msgHandler = new SimpleDemo(); // 实现IMsgHandlerFace接口的类 + Wechat wechat = new Wechat(msgHandler, qrPath); // 【注入】 + wechat.start(); // 启动服务,会在qrPath下生成一张二维码图片,扫描即可登陆,注意,二维码图片如果超过一定时间未扫描会过期,过期时会自动更新,所以你可能需要重新打开图片 + } +} diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/demo1/SimpleDemo.java similarity index 65% rename from src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java rename to src/test/java/cn/zhouyafeng/itchat4j/demo/demo1/SimpleDemo.java index 847de29..597fa89 100644 --- a/src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java +++ b/src/test/java/cn/zhouyafeng/itchat4j/demo/demo1/SimpleDemo.java @@ -1,4 +1,4 @@ -package cn.zhouyafeng.itchat4j.demo; +package cn.zhouyafeng.itchat4j.demo.demo1; import java.io.File; import java.text.SimpleDateFormat; @@ -8,7 +8,7 @@ import com.alibaba.fastjson.JSONObject; -import cn.zhouyafeng.itchat4j.Wechat; +import cn.zhouyafeng.itchat4j.api.MessageTools; import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; import cn.zhouyafeng.itchat4j.utils.tools.DownloadTools; @@ -26,27 +26,21 @@ public class SimpleDemo implements IMsgHandlerFace { @Override public String textMsgHandle(JSONObject msg) { - // String docFilePath = "D:/itchat4j/pic/test.docx"; - // String pngFilePath = "D:/itchat4j/pic/test.png"; - // String pdfFilePath = "D:/itchat4j/pic/测试.pdf"; - // String txtFilePath = "D:/itchat4j/pic/test.txt"; - // MessageTools.sendFileMsgByNickName("yaphone", docFilePath); - // MessageTools.sendFileMsgByNickName("yaphone", pngFilePath); - // MessageTools.sendFileMsgByNickName("yaphone", pdfFilePath); - // MessageTools.sendFileMsgByNickName("yaphone", txtFilePath); - // logger.info("info" + msg.toJSONString()); - // System.out.println("*************"); - LOG.info("debug" + msg.toJSONString()); - String text = msg.getString("Text"); - return text; - // return null; + String docFilePath = "D:/itchat4j/pic/test.docx"; // 这里是需要发送的文件的路径 + if (!msg.getBoolean("groupMsg")) { // 群消息不处理 + String userId = msg.getString("FromUserName"); + MessageTools.sendFileMsgByUserId(userId, docFilePath); // 发送文件 + String text = msg.getString("Text"); // 发送文本消息,也可调用MessageTools.sendFileMsgByUserId(userId,text); + return text; + } + return null; } @Override public String picMsgHandle(JSONObject msg) { - String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); - String picPath = "D://itchat4j/pic" + File.separator + fileName + ".jpg"; - DownloadTools.getDownloadFn(msg, MsgTypeEnum.PIC.getType(), picPath); + String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());// 这里使用收到图片的时间作为文件名 + String picPath = "D://itchat4j/pic" + File.separator + fileName + ".jpg"; // 调用此方法来保存图片 + DownloadTools.getDownloadFn(msg, MsgTypeEnum.PIC.getType(), picPath); // 保存图片的路径 return "图片保存成功"; } @@ -72,10 +66,4 @@ public String nameCardMsgHandle(JSONObject msg) { return "收到名片消息"; } - public static void main(String[] args) { - IMsgHandlerFace msgHandler = new SimpleDemo(); - Wechat wechat = new Wechat(msgHandler, "D://itchat4j/login"); - wechat.start(); - } - } diff --git a/src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java b/src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java deleted file mode 100644 index f7c6558..0000000 --- a/src/test/java/cn/zhouyafeng/itchat4j/demo/demo2/SimpleDemo2.java +++ /dev/null @@ -1,88 +0,0 @@ -package cn.zhouyafeng.itchat4j.demo.demo2; - -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.fastjson.JSONObject; - -import cn.zhouyafeng.itchat4j.Wechat2; -import cn.zhouyafeng.itchat4j.api.MessageTools; -import cn.zhouyafeng.itchat4j.api.WechatTools; -import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace; -import cn.zhouyafeng.itchat4j.utils.enums.MsgTypeEnum; -import cn.zhouyafeng.itchat4j.utils.tools.DownloadTools; - -/** - * - * @author https://github.com/yaphone - * @date 创建时间:2017年5月13日 下午2:44:58 - * @version 1.0 - * - */ -public class SimpleDemo2 implements IMsgHandlerFace { - - private static final Logger LOG = LoggerFactory.getLogger(SimpleDemo2.class); - - @Override - public String textMsgHandle(JSONObject msg) { - String docFilePath = "D:/itchat4j/pic/test.docx"; - // String pngFilePath = "D:/itchat4j/pic/test.png"; - // String pdfFilePath = "D:/itchat4j/pic/测试.pdf"; - // String txtFilePath = "D:/itchat4j/pic/test.txt"; - MessageTools.sendFileMsgByUserId(msg.getString("FromUserName"), docFilePath); - // MessageTools.sendFileMsgByNickName("yaphone", pngFilePath); - // MessageTools.sendFileMsgByNickName("yaphone", pdfFilePath); - // MessageTools.sendFileMsgByNickName("yaphone", txtFilePath); - // logger.info("info" + msg.toJSONString()); - // System.out.println("*************"); - if (!msg.getBoolean("groupMsg")) { - // MessageTools.sendFileMsgByUserId(msg.getString("FromUserName"), - // docFilePath); - LOG.info("联系人总数: " + WechatTools.getContactList().size()); - String text = msg.getString("Text"); - return text; - } - return null; - // return null; - } - - @Override - public String picMsgHandle(JSONObject msg) { - String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); - String picPath = "D://itchat4j/pic" + File.separator + fileName + ".jpg"; - DownloadTools.getDownloadFn(msg, MsgTypeEnum.PIC.getType(), picPath); - return "图片保存成功"; - } - - @Override - public String voiceMsgHandle(JSONObject msg) { - String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); - String voicePath = "D://itchat4j/voice" + File.separator + fileName + ".mp3"; - DownloadTools.getDownloadFn(msg, MsgTypeEnum.VOICE.getType(), voicePath); - return "声音保存成功"; - } - - @Override - public String viedoMsgHandle(JSONObject msg) { - System.out.println(msg); - String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); - String viedoPath = "D://itchat4j/viedo" + File.separator + fileName + ".mp4"; - DownloadTools.getDownloadFn(msg, MsgTypeEnum.VIEDO.getType(), viedoPath); - return "视频保存成功"; - } - - @Override - public String nameCardMsgHandle(JSONObject msg) { - return "收到名片消息"; - } - - public static void main(String[] args) { - IMsgHandlerFace msgHandler = new SimpleDemo2(); - Wechat2 wechat = new Wechat2(msgHandler, "D://itchat4j/login"); - wechat.start(); - } -}