Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions scripts/liepin-send-dom.node-test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,65 @@ test("do not mistake chat drawer history for a priority modal", async () => {
assert.equal(result.success, true);
});

test("find chat composer when Liepin changes the container class", async () => {
const document = makeDocument(`
<section class="im-panel-v2">
<div class="im-ui-msg-list-content-v2">
<textarea></textarea>
<button class="ant-im-btn">发送</button>
</div>
</section>
`);
const requestRecords = [];
const input = document.querySelector("textarea");
document.querySelector(".ant-im-btn").addEventListener("click", () => {
input.value = "";
requestRecords.push({
url: "https://api-c.liepin.com/api/com.liepin.im.c.chat.send-push",
status: 200,
});
});

const result = await runLiepinSend(document, {
message: "你好",
requestRecords,
sleep: async () => {},
});

assert.equal(result.success, true);
});

test("ignore login text in chat history when the chat panel is a dialog", async () => {
const document = makeDocument(`
<div role="dialog" class="chat-drawer-v2">
<header>我的沟通</header>
<div>不支持此消息查看,请登录“猎聘APP”查看消息内容!</div>
<div class="im-ui-msg-list-content-v2">
<textarea></textarea>
<button class="ant-im-btn">发送</button>
</div>
</div>
`);
const requestRecords = [];
const input = document.querySelector("textarea");
document.querySelector(".ant-im-btn").addEventListener("click", () => {
input.value = "";
requestRecords.push({
url: "https://api-c.liepin.com/api/com.liepin.im.c.chat.send-push",
status: 200,
});
});

const result = await runLiepinSend(document, {
message: "你好",
requestRecords,
sleep: async () => {},
});

assert.equal(result.blockedModal, false);
assert.equal(result.success, true);
});

test("close only visible priority communication modal before sending", async () => {
const document = makeDocument(`
<div class="ant-modal" data-modal="priority">
Expand Down
51 changes: 37 additions & 14 deletions src-tauri/src/rpa/liepin/send_text.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ async function closePriorityModal(modal, document, sleep) {
}

function classifyModal(modal) {
if (modal.querySelector(CHAT_CONTAINER_SELECTOR)) return "other";
if (findChatContainer(modal)) return "other";
const text = textOf(modal);
const hasPriorityTitle = Array.from(modal.querySelectorAll("h1, h2, h3, [class*='title'], [class*='header'], div, span"))
.some((node) => textOf(node) === "优先沟通");
Expand Down Expand Up @@ -136,19 +136,6 @@ async function handleKnownModal(document, sleep) {
};
}

function findChatContainer(document) {
const marker = findVisible(Array.from(document.querySelectorAll(CHAT_CONTAINER_SELECTOR)));
if (!marker) return null;
let candidate = marker;
for (let container = marker; container && container !== document.body; container = container.parentElement) {
if (findChatInput(container)) {
candidate = container;
if (findAnySendButton(container)) return container;
}
}
return candidate;
}

function findAnySendButton(container) {
return container
? Array.from(container.querySelectorAll(SEND_BUTTON_SELECTOR))
Expand All @@ -163,6 +150,42 @@ function findChatInput(container) {
return inputs.find((node) => !node.disabled && !node.readOnly) || null;
}

function findInputContainer(input, boundary) {
for (let container = input?.parentElement; container; container = container.parentElement) {
if (findAnySendButton(container)) return container;
if (container === boundary) break;
}
return null;
}

function findChatContainer(root) {
const document = root.nodeType === 9 ? root : root.ownerDocument;
const boundary = root.nodeType === 9 ? document.body : root;
const marker = findVisible(Array.from(root.querySelectorAll(CHAT_CONTAINER_SELECTOR)));
if (marker) {
let candidate = marker;
for (let container = marker; container && container !== boundary; container = container.parentElement) {
if (findChatInput(container)) {
candidate = container;
if (findAnySendButton(container)) return container;
}
}
return candidate;
}

const markedInput = findVisible(Array.from(root.querySelectorAll(`[${CHAT_INPUT_MARKER}]`)));
const inputs = Array.from(root.querySelectorAll(INPUT_SELECTOR)).filter((node) => isVisible(node)
&& !node.disabled && !node.readOnly);
if (markedInput) {
inputs.unshift(markedInput);
}
for (const input of inputs) {
const container = findInputContainer(input, boundary);
if (container) return container;
}
return null;
}

function markLiepinChatInput(document) {
document.querySelectorAll(`[${CHAT_INPUT_MARKER}]`)
.forEach((node) => node.removeAttribute(CHAT_INPUT_MARKER));
Expand Down
Loading