From 96f15bb969b7e78420c5e34cc9256c6c431a23ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=B9=E7=94=B2=E4=BB=91?= Date: Fri, 26 Aug 2022 14:59:55 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E5=85=BC=E5=AE=B9=E4=B8=BB=E5=8A=A8?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=A5=BD=E5=8F=8B;=E5=8F=AF=E5=8F=98?= =?UTF-8?q?=E5=9B=9E=E5=A4=8D=E5=86=85=E5=AE=B9=E5=89=8D=E7=BC=80;?= =?UTF-8?q?=E5=85=B6=E4=BB=96=E5=B7=B2=E7=9F=A5=E9=97=AE=E9=A2=98=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../worktool/model/WeworkMessageBean.java | 2 + .../worktool/service/WeworkController.kt | 1 + .../worktool/service/WeworkLoopImpl.kt | 5 +- .../worktool/service/WeworkOperationImpl.kt | 162 ++++++++++-------- .../worktool/utils/AccessibilityUtil.kt | 1 + .../yameida/worktool/utils/WeworkRoomUtil.kt | 7 + 6 files changed, 109 insertions(+), 69 deletions(-) diff --git a/app/src/main/java/org/yameida/worktool/model/WeworkMessageBean.java b/app/src/main/java/org/yameida/worktool/model/WeworkMessageBean.java index 37cd4d5..345a1ba 100644 --- a/app/src/main/java/org/yameida/worktool/model/WeworkMessageBean.java +++ b/app/src/main/java/org/yameida/worktool/model/WeworkMessageBean.java @@ -139,6 +139,8 @@ public class WeworkMessageBean { public String receivedName; //内容移除了@me public String receivedContent; + //回复内容前缀 + public String prefix; //想要at的昵称 public String at; //原始内容text diff --git a/app/src/main/java/org/yameida/worktool/service/WeworkController.kt b/app/src/main/java/org/yameida/worktool/service/WeworkController.kt index eb780a7..f2aa5be 100644 --- a/app/src/main/java/org/yameida/worktool/service/WeworkController.kt +++ b/app/src/main/java/org/yameida/worktool/service/WeworkController.kt @@ -59,6 +59,7 @@ object WeworkController { * @param message#originalContent 原始消息的内容 * @param message#textType 原始消息的消息类型 * @param message#receivedContent 回复内容 + * @param message#prefix 回复内容前缀 * @see WeworkMessageBean.TEXT_TYPE */ @RequestMapping diff --git a/app/src/main/java/org/yameida/worktool/service/WeworkLoopImpl.kt b/app/src/main/java/org/yameida/worktool/service/WeworkLoopImpl.kt index 2f5fbca..fedb56d 100644 --- a/app/src/main/java/org/yameida/worktool/service/WeworkLoopImpl.kt +++ b/app/src/main/java/org/yameida/worktool/service/WeworkLoopImpl.kt @@ -5,7 +5,6 @@ import android.view.accessibility.AccessibilityNodeInfo import androidx.core.text.isDigitsOnly import com.blankj.utilcode.util.LogUtils import org.yameida.worktool.Constant -import org.yameida.worktool.Demo import org.yameida.worktool.model.WeworkMessageBean import org.yameida.worktool.service.WeworkController.mainLoopRunning import org.yameida.worktool.utils.* @@ -73,7 +72,8 @@ object WeworkLoopImpl { val nameList = passFriendRequest() if (nameList.isEmpty()) break - Demo.test2(nameList[0]) + //todo 可自定义执行任务 +// Demo.test2(nameList[0]) } } return true @@ -105,6 +105,7 @@ object WeworkLoopImpl { val title = titleList.joinToString() LogUtils.v("聊天: $title") log("聊天: $title") + //聊天消息列表 1ListView 0RecycleView xViewGroup val list = AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView) if (list != null) { LogUtils.v("消息条数: " + list.childCount) diff --git a/app/src/main/java/org/yameida/worktool/service/WeworkOperationImpl.kt b/app/src/main/java/org/yameida/worktool/service/WeworkOperationImpl.kt index 259e267..b03a94b 100644 --- a/app/src/main/java/org/yameida/worktool/service/WeworkOperationImpl.kt +++ b/app/src/main/java/org/yameida/worktool/service/WeworkOperationImpl.kt @@ -45,6 +45,7 @@ object WeworkOperationImpl { * @param originalContent 原始消息的内容 * @param textType 原始消息的消息类型 * @param receivedContent 回复内容 + * @param prefix 回复内容前缀 * @see WeworkMessageBean.TEXT_TYPE */ fun replyMessage( @@ -52,11 +53,13 @@ object WeworkOperationImpl { receivedName: String?, originalContent: String, textType: Int, - receivedContent: String + receivedContent: String, + prefix: String = "[自动回复]" ): Boolean { for (title in titleList) { if (WeworkRoomUtil.intoRoom(title)) { if (WeworkTextUtil.longClickMessageItem( + //聊天消息列表 1ListView 0RecycleView xViewGroup AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView), textType, receivedName, @@ -65,7 +68,7 @@ object WeworkOperationImpl { ) ) { LogUtils.v("开始回复") - sendChatMessage(receivedContent, "[自动回复]") + sendChatMessage(receivedContent, prefix) LogUtils.d("$title: 回复成功") WeworkLoopImpl.getChatMessageList() return true @@ -73,9 +76,9 @@ object WeworkOperationImpl { LogUtils.d("$title: 回复失败 直接发送答案") error("$title: 回复失败 直接发送答案 $receivedContent") if (receivedName == null) { - sendChatMessage(receivedContent, "[自动回复]【$originalContent】\n") + sendChatMessage(receivedContent, "$prefix【$originalContent】\n") } else { - sendChatMessage(receivedContent, "[自动回复]【$originalContent】@$receivedName\n") + sendChatMessage(receivedContent, "$prefix【$originalContent】@$receivedName\n") } WeworkLoopImpl.getChatMessageList() } @@ -108,6 +111,7 @@ object WeworkOperationImpl { for (title in titleList) { if (WeworkRoomUtil.intoRoom(title)) { if (WeworkTextUtil.longClickMessageItem( + //聊天消息列表 1ListView 0RecycleView xViewGroup AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView), textType, receivedName, @@ -167,63 +171,6 @@ object WeworkOperationImpl { return true } - fun getGroupQrcode(groupName: String): Boolean { - if (WeworkRoomUtil.intoRoom(groupName) && WeworkRoomUtil.intoGroupManager()) { - val tvList = AccessibilityUtil.findAllOnceByClazz(getRoot(), Views.TextView) - tvList.forEachIndexed { index, tv -> - if (tv.text != null && tv.text.contains("微信用户创建")) { - if (index + 1 < tvList.size) { - val tvQr = tvList[index + 1] - AccessibilityUtil.performClick(tvQr) - } - } - } - AccessibilityUtil.findOneByText(getRoot(), "保存到相册") - val startTime = System.currentTimeMillis() - var currentTime = startTime - while (currentTime - startTime <= Constant.CHANGE_PAGE_INTERVAL * 5) { - AccessibilityUtil.findOnceByClazz(getRoot(), Views.ProgressBar) ?: break - sleep(Constant.POP_WINDOW_INTERVAL / 5) - currentTime = System.currentTimeMillis() - } - if (AccessibilityUtil.findTextAndClick(getRoot(), "保存到相册")) { - sleep(Constant.CHANGE_PAGE_INTERVAL) - val fileDirPath = "/storage/emulated/0/DCIM/WeixinWork" - val fileDir = FileUtils.getFileByPath(fileDirPath) - if (fileDir.isDirectory) { - for (file in fileDir.listFiles().filter { it.name.endsWith(".jpg") }) { - val fileTime = file.name.replace("mmexport", "") - .replace(".jpg", "") - LogUtils.v("fileTime: $fileTime") - if (fileTime.isNotBlank()) { - if (fileTime.toLong() > currentTime) { - LogUtils.d("找到最新保存二维码图片: $fileTime") - try { - val bitmap = ImageUtils.bytes2Bitmap(file.readBytes()) - val mDecoder = QRCodeDecoder.Builder().build() - val qrcode = mDecoder.decode(bitmap) - LogUtils.e("group: $groupName qrcode: $qrcode") - val weworkMessageBean = WeworkMessageBean() - weworkMessageBean.type = WeworkMessageBean.GET_GROUP_QRCODE - weworkMessageBean.groupName = groupName - weworkMessageBean.qrcode = qrcode - WeworkController.weworkService.webSocketManager.send( - weworkMessageBean - ) - return true - } catch (e: Exception) { - e.printStackTrace() - LogUtils.e(e) - } - } - } - } - } - } - } - return false - } - /** * 进入群聊并修改群配置 * 群名称、群公告、拉人、踢人 @@ -443,7 +390,7 @@ object WeworkOperationImpl { friend: WeworkMessageBean.Friend ): Boolean { goHome() - val list = AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView) + val list = AccessibilityUtil.findOneByClazz(getRoot(), Views.RecyclerView, Views.ListView, Views.ViewGroup) if (list != null) { val frontNode = AccessibilityUtil.findFrontNode(list) val textViewList = AccessibilityUtil.findAllOnceByClazz(frontNode, Views.TextView) @@ -452,9 +399,19 @@ object WeworkOperationImpl { val multiButton: AccessibilityNodeInfo = textViewList[textViewList.size - 1] AccessibilityUtil.performClick(multiButton) sleep(Constant.POP_WINDOW_INTERVAL) - val listViewList = AccessibilityUtil.findAllByClazz(getRoot(), Views.ListView) - if (!listViewList.isNullOrEmpty()) { - if (AccessibilityUtil.findTextAndClick(listViewList.last(), "添加客户", "添加居民", "加微信")) { + val list = AccessibilityUtil.findAllByClazz(getRoot(), Views.ListView).lastOrNull() + if (list != null) { + val button = AccessibilityUtil.findOneByText(list, "添加客户", "添加居民", "加微信") + if (button != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + AccessibilityUtil.performClick(button) + sleep(Constant.POP_WINDOW_INTERVAL) + if (AccessibilityUtil.findOnceByText(list, "添加客户", "添加居民", "加微信") != null) { + AccessibilityUtil.clickByNode(WeworkController.weworkService, button) + } + } else { + AccessibilityUtil.performClick(button) + } AccessibilityUtil.findTextAndClick(getRoot(), "搜索手机号添加") AccessibilityUtil.findTextInput(getRoot(), friend.phone.trim()) if (AccessibilityUtil.findTextAndClick(getRoot(), "网络查找手机")) { @@ -585,6 +542,7 @@ object WeworkOperationImpl { * extraText 转发是否附加一条文本 */ private fun relaySelectTarget(selectList: List, extraText: String? = null): Boolean { + //聊天消息列表 1ListView 0RecycleView xViewGroup val list = AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView) if (list != null) { val frontNode = AccessibilityUtil.findFrontNode(list, 2) @@ -730,6 +688,7 @@ object WeworkOperationImpl { LogUtils.e("未找到添加成员按钮") return false } + //群详情列表 val list = AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView) if (list != null) { val frontNode = AccessibilityUtil.findFrontNode(list, 2) @@ -797,6 +756,7 @@ object WeworkOperationImpl { LogUtils.e("未找到删除成员按钮") return false } + //群详情列表 val list = AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView) if (list != null) { val frontNode = AccessibilityUtil.findFrontNode(list, 2) @@ -888,10 +848,14 @@ object WeworkOperationImpl { * 发送消息+@at */ private fun sendChatMessage(text: String, prefix: String = "", at: String? = null) { + val voiceFlag = AccessibilityUtil.findOnceByText(getRoot(), "按住 说话", "按住说话", exact = true) + if (voiceFlag != null) { + AccessibilityUtil.performClickWithSon(AccessibilityUtil.findFrontNode(voiceFlag)) + } var atFailed = false if (!at.isNullOrEmpty()) { AccessibilityUtil.findTextInput(getRoot(), "@") - val atFlag = AccessibilityUtil.findOneByText(getRoot(), "选择提醒的人", timeout = 2000) + val atFlag = AccessibilityUtil.findOneByText(getRoot(), "选择提醒的人", timeout = 2000, exact = true) if (atFlag != null) { val rv = AccessibilityUtil.findOneByClazz(getRoot(), Views.RecyclerView) if (rv != null) { @@ -926,7 +890,8 @@ object WeworkOperationImpl { } } val content = if (atFailed) "@$at $prefix$text" else "$prefix$text" - if (AccessibilityUtil.findTextInput(getRoot(), content, append = !atFailed)) { + val append = !at.isNullOrEmpty() && !atFailed + if (AccessibilityUtil.findTextInput(getRoot(), content, append = append)) { val sendButton = AccessibilityUtil.findAllByClazz(getRoot(), Views.Button) .firstOrNull { it.text == "发送" } if (sendButton != null) { @@ -993,6 +958,9 @@ object WeworkOperationImpl { list.refresh() } if (AccessibilityUtil.findTextAndClick(getRoot(), "确定")) { + sleep(Constant.POP_WINDOW_INTERVAL) + //可能有两次确定 另一次为添加新tag + AccessibilityUtil.findTextAndClick(getRoot(), "确定") return true } } @@ -1000,4 +968,64 @@ object WeworkOperationImpl { return false } + /** + * 获取群二维码并上传后台 + */ + fun getGroupQrcode(groupName: String): Boolean { + if (WeworkRoomUtil.intoRoom(groupName) && WeworkRoomUtil.intoGroupManager()) { + val tvList = AccessibilityUtil.findAllOnceByClazz(getRoot(), Views.TextView) + tvList.forEachIndexed { index, tv -> + if (tv.text != null && tv.text.contains("微信用户创建")) { + if (index + 1 < tvList.size) { + val tvQr = tvList[index + 1] + AccessibilityUtil.performClick(tvQr) + } + } + } + AccessibilityUtil.findOneByText(getRoot(), "保存到相册") + val startTime = System.currentTimeMillis() + var currentTime = startTime + while (currentTime - startTime <= Constant.CHANGE_PAGE_INTERVAL * 5) { + AccessibilityUtil.findOnceByClazz(getRoot(), Views.ProgressBar) ?: break + sleep(Constant.POP_WINDOW_INTERVAL / 5) + currentTime = System.currentTimeMillis() + } + if (AccessibilityUtil.findTextAndClick(getRoot(), "保存到相册")) { + sleep(Constant.CHANGE_PAGE_INTERVAL) + val fileDirPath = "/storage/emulated/0/DCIM/WeixinWork" + val fileDir = FileUtils.getFileByPath(fileDirPath) + if (fileDir.isDirectory) { + for (file in fileDir.listFiles().filter { it.name.endsWith(".jpg") }) { + val fileTime = file.name.replace("mmexport", "") + .replace(".jpg", "") + LogUtils.v("fileTime: $fileTime") + if (fileTime.isNotBlank()) { + if (fileTime.toLong() > currentTime) { + LogUtils.d("找到最新保存二维码图片: $fileTime") + try { + val bitmap = ImageUtils.bytes2Bitmap(file.readBytes()) + val mDecoder = QRCodeDecoder.Builder().build() + val qrcode = mDecoder.decode(bitmap) + LogUtils.e("group: $groupName qrcode: $qrcode") + val weworkMessageBean = WeworkMessageBean() + weworkMessageBean.type = WeworkMessageBean.GET_GROUP_QRCODE + weworkMessageBean.groupName = groupName + weworkMessageBean.qrcode = qrcode + WeworkController.weworkService.webSocketManager.send( + weworkMessageBean + ) + return true + } catch (e: Exception) { + e.printStackTrace() + LogUtils.e(e) + } + } + } + } + } + } + } + return false + } + } \ No newline at end of file diff --git a/app/src/main/java/org/yameida/worktool/utils/AccessibilityUtil.kt b/app/src/main/java/org/yameida/worktool/utils/AccessibilityUtil.kt index b8457a2..c320e90 100644 --- a/app/src/main/java/org/yameida/worktool/utils/AccessibilityUtil.kt +++ b/app/src/main/java/org/yameida/worktool/utils/AccessibilityUtil.kt @@ -184,6 +184,7 @@ object AccessibilityUtil { } nodeInfo = nodeInfo.parent } + LogUtils.e("performClick failed! ${nodeInfo?.className}") return false } diff --git a/app/src/main/java/org/yameida/worktool/utils/WeworkRoomUtil.kt b/app/src/main/java/org/yameida/worktool/utils/WeworkRoomUtil.kt index 75eb171..2d9f365 100644 --- a/app/src/main/java/org/yameida/worktool/utils/WeworkRoomUtil.kt +++ b/app/src/main/java/org/yameida/worktool/utils/WeworkRoomUtil.kt @@ -57,6 +57,7 @@ object WeworkRoomUtil { */ fun getRoomTitle(print: Boolean = true): ArrayList { val titleList = arrayListOf() + //聊天消息列表 1ListView 0RecycleView xViewGroup val list = AccessibilityUtil.findOnceByClazz(getRoot(), Views.ListView) if (list != null) { val frontNode = findFrontNode(list.parent.parent) @@ -102,6 +103,7 @@ object WeworkRoomUtil { AccessibilityUtil.performClick(searchButton) AccessibilityUtil.findTextInput(getRoot(), title.replace("…", "").replace("-.*$".toRegex(), "")) sleep(Constant.CHANGE_PAGE_INTERVAL) + //消息页搜索结果列表 val selectListView = findOneByClazz(getRoot(), Views.ListView) val imageView = AccessibilityUtil.findOnceByClazz(selectListView, Views.ImageView) if (imageView != null) { @@ -129,6 +131,7 @@ object WeworkRoomUtil { if (AccessibilityUtil.findOnceByText(getRoot(), "全部群成员", "微信用户创建") != null) { return true } + //群详情列表 val list = findOneByClazz(getRoot(), Views.ListView) if (list != null) { val frontNode = AccessibilityUtil.findFrontNode(list.parent.parent) @@ -153,6 +156,7 @@ object WeworkRoomUtil { if (AccessibilityUtil.findOneByText(getRoot(), "设置聊天背景") != null) { return true } + //同群详情列表 val list = findOneByClazz(getRoot(), Views.ListView) if (list != null) { val frontNode = AccessibilityUtil.findFrontNode(list.parent.parent) @@ -210,6 +214,7 @@ object WeworkRoomUtil { * listview前兄弟控件 && text包含外部群 */ private fun isExternalGroup(): Boolean { + //聊天消息列表 1ListView 0RecycleView xViewGroup val listView = AccessibilityUtil.findOnceByClazz(getRoot(), Views.ListView, limitDepth = null, depth = 0) if (listView != null) { val frontNode = findFrontNode(listView) @@ -226,8 +231,10 @@ object WeworkRoomUtil { * 有列表和输入框 */ private fun isSingleChat(): Boolean { + //聊天消息列表 1ListView 0RecycleView xViewGroup val list = AccessibilityUtil.findOnceByClazz(getRoot(), Views.ListView) val editText = AccessibilityUtil.findOnceByClazz(getRoot(), Views.EditText) + ?: AccessibilityUtil.findOnceByText(getRoot(), "按住 说话", "按住说话", exact = true) if (list != null && editText != null) { return true }