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 d2f781a..ad2d7d3 100644 --- a/app/src/main/java/org/yameida/worktool/model/WeworkMessageBean.java +++ b/app/src/main/java/org/yameida/worktool/model/WeworkMessageBean.java @@ -38,6 +38,7 @@ public class WeworkMessageBean { * 打卡 CLOCK_IN * 切换企业 SWITCH_CORP * 推送链接 PUSH_LINK + * 撤回消息 RECALL_MESSAGE *

* 非操作类型 300 * 机器人普通日志记录 ROBOT_LOG @@ -81,6 +82,7 @@ public class WeworkMessageBean { public static final int CLOCK_IN = 222; public static final int SWITCH_CORP = 223; public static final int PUSH_LINK = 224; + public static final int RECALL_MESSAGE = 225; public static final int ROBOT_LOG = 301; public static final int ROBOT_ERROR_LOG = 302; diff --git a/app/src/main/java/org/yameida/worktool/service/MyLooper.kt b/app/src/main/java/org/yameida/worktool/service/MyLooper.kt index a101fef..4d1479a 100644 --- a/app/src/main/java/org/yameida/worktool/service/MyLooper.kt +++ b/app/src/main/java/org/yameida/worktool/service/MyLooper.kt @@ -166,6 +166,9 @@ object MyLooper { WeworkMessageBean.PUSH_LINK -> { WeworkController.pushLink(message) } + WeworkMessageBean.RECALL_MESSAGE -> { + WeworkController.recallMessage(message) + } WeworkMessageBean.DISMISS_GROUP -> { WeworkController.dismissGroup(message) } 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 77b2cc6..d1079f5 100644 --- a/app/src/main/java/org/yameida/worktool/service/WeworkController.kt +++ b/app/src/main/java/org/yameida/worktool/service/WeworkController.kt @@ -363,6 +363,25 @@ object WeworkController { ) } + /** + * 撤回消息 + * @see WeworkMessageBean.RECALL_MESSAGE + * @param message#titleList 房间名称 + * @param message#originalContent 原始消息的内容 + * @param message#textType 原始消息的消息类型 + * @see WeworkMessageBean.TEXT_TYPE + */ + @RequestMapping + fun recallMessage(message: WeworkMessageBean): Boolean { + LogUtils.d("recallMessage(): ${message.titleList} ${message.originalContent} ${message.textType}") + return WeworkOperationImpl.recallMessage( + message, + message.titleList, + message.originalContent, + message.textType + ) + } + /** * 按手机号添加好友 * @see WeworkMessageBean.ADD_FRIEND_BY_PHONE 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 6f8f0d3..debcaae 100644 --- a/app/src/main/java/org/yameida/worktool/service/WeworkOperationImpl.kt +++ b/app/src/main/java/org/yameida/worktool/service/WeworkOperationImpl.kt @@ -764,6 +764,46 @@ object WeworkOperationImpl { } } + /** + * 撤回消息 + * @see WeworkMessageBean.RECALL_MESSAGE + * @param titleList 房间名称 + * @param originalContent 原始消息的内容 + * @param textType 原始消息的消息类型 + * @see WeworkMessageBean.TEXT_TYPE + */ + fun recallMessage( + message: WeworkMessageBean, + titleList: List, + originalContent: String, + textType: Int + ): Boolean { + val startTime = System.currentTimeMillis() + for (title in titleList) { + if (WeworkRoomUtil.intoRoom(title)) { + if (WeworkTextUtil.longClickMyMessageItem( + //聊天消息列表 1ListView 0RecycleView xViewGroup + AccessibilityUtil.findOneByClazz(getRoot(), Views.ListView), + textType, + originalContent, + "撤回" + ) + ) { + LogUtils.d("撤回成功") + uploadCommandResult(message, ExecCallbackBean.SUCCESS, "", startTime, titleList, listOf()) + return true + } else { + LogUtils.e("撤回失败 未找到目标消息") + uploadCommandResult(message, ExecCallbackBean.ERROR_TARGET, "撤回失败 未找到目标消息", startTime, listOf(), titleList) + return false + } + } + } + LogUtils.e("撤回失败 未找到房间") + uploadCommandResult(message, ExecCallbackBean.ERROR_TARGET, "撤回失败 未找到房间", startTime, listOf(), titleList) + return false + } + /** * 手机号添加好友或修改好友信息 * @see WeworkMessageBean.ADD_FRIEND_BY_PHONE diff --git a/app/src/main/java/org/yameida/worktool/utils/WeworkTextUtil.kt b/app/src/main/java/org/yameida/worktool/utils/WeworkTextUtil.kt index 2a925e7..178e159 100644 --- a/app/src/main/java/org/yameida/worktool/utils/WeworkTextUtil.kt +++ b/app/src/main/java/org/yameida/worktool/utils/WeworkTextUtil.kt @@ -280,6 +280,15 @@ object WeworkTextUtil { LogUtils.v("textType: $textType") return textType } + } else if (Views.ImageView.equals(relativeLayoutItem.getChild(1).className)) { + LogUtils.v("头像在右边 本条消息发送者为自己") + var textType = WeworkMessageBean.TEXT_TYPE_UNKNOWN + val subLayout = relativeLayoutItem.getChild(0) + if (subLayout.childCount > 0) { + textType = WeworkTextUtil.getTextType(subLayout) + LogUtils.v("textType: $textType") + return textType + } } } return WeworkMessageBean.TEXT_TYPE_UNKNOWN @@ -326,8 +335,9 @@ object WeworkTextUtil { } /** - * 群聊 长按消息条目 + * 长按消息条目 * 复制、转发、回复、收藏、置顶、多选、日程、待办、翻译、删除 + * 适用左侧发言者 * @param node 消息列表节点 * @param replyTextType 带回复消息类型 * @param replyNick 待回复人姓名 @@ -400,6 +410,50 @@ object WeworkTextUtil { return false } + /** + * 长按消息条目 + * 复制、转发、回复、收藏、置顶、多选、日程、待办、翻译、删除、撤回 + * 适用自己发言者 + * @param node 消息列表节点 + * @param replyTextType 带回复消息类型 + * @param replyContent 待回复内容 + * @param key 复制、转发、回复、收藏、多选 + * @return true 进行了长按 否则 false + */ + fun longClickMyMessageItem( + node: AccessibilityNodeInfo?, + replyTextType: Int, + replyContent: String, + key: String + ): Boolean { + if (node == null) return false + for (i in 0 until node.childCount) { + val item = node.getChild(node.childCount - 1 - i) ?: continue + val frontNode = getMyMessageListNode(item) + if (frontNode != null) { + val textType = getTextTypeFromItem(item) + if (replyTextType == WeworkMessageBean.TEXT_TYPE_UNKNOWN || replyTextType == textType) { + if (replyTextType == WeworkMessageBean.TEXT_TYPE_IMAGE) { + return longClickMyMessageItem(item, WeworkMessageBean.ROOM_TYPE_INTERNAL_CONTACT, key) + } + if ((replyTextType == WeworkMessageBean.TEXT_TYPE_FILE || replyTextType == WeworkMessageBean.TEXT_TYPE_VIDEO) + && replyContent.contains("###")) { + val replyContentList = replyContent.split("###") + if (AccessibilityUtil.findOnceByText(frontNode, replyContentList[0]) != null + && AccessibilityUtil.findOnceByText(frontNode, replyContentList[1]) != null) { + return longClickMyMessageItem(item, WeworkMessageBean.ROOM_TYPE_INTERNAL_GROUP, key) + } + } + val textNode = AccessibilityUtil.findOnceByText(frontNode, replyContent, exact = true) + if (textNode != null && replyContent.isNotEmpty()) { + return longClickMyMessageItem(item, WeworkMessageBean.ROOM_TYPE_INTERNAL_CONTACT, key) + } + } + } + } + return false + } + private fun longClickMessageItem(item: AccessibilityNodeInfo, roomType: Int, key: String): Boolean { val backNode = getMessageListNode(item, roomType) AccessibilityUtil.performLongClickWithSon(backNode) @@ -415,8 +469,26 @@ object WeworkTextUtil { return false } + private fun longClickMyMessageItem(item: AccessibilityNodeInfo, roomType: Int, key: String): Boolean { + val frontNode = getMyMessageListNode(item) + AccessibilityUtil.performLongClickWithSon(frontNode) + sleep(Constant.POP_WINDOW_INTERVAL) + val optionRvList = findAllByClazz(getRoot(), Views.RecyclerView, Views.ViewGroup) + for (optionRv in optionRvList) { + val keyTv = AccessibilityUtil.findOnceByText(optionRv, key, exact = true) + if (keyTv != null) { + AccessibilityUtil.performClick(keyTv) + if (AccessibilityExtraUtil.loadingPage("CustomDialog", timeout = Constant.POP_WINDOW_INTERVAL)) { + AccessibilityUtil.findTextAndClick(getRoot(), "确定", exact = true) + } + return true + } + } + return false + } + /** - * 群聊 提取消息主体框节点(昵称下面的气泡框) + * 提取消息主体框节点(昵称下面的气泡框) * 适用于左侧发言者 * @param item 消息item节点 */ @@ -434,4 +506,17 @@ object WeworkTextUtil { } return null } + + /** + * 提取消息主体框节点(昵称下面的气泡框) + * 适用于自己发言者 + * @param item 消息item节点 + */ + private fun getMyMessageListNode(item: AccessibilityNodeInfo): AccessibilityNodeInfo? { + val node = AccessibilityUtil.findAllOnceByClazz(item, Views.ImageView).lastOrNull() + if (node?.parent?.getChild(0) != node) { + return AccessibilityUtil.findFrontNode(node) + } + return null + } } \ No newline at end of file