Skip to content

Commit 246d0ad

Browse files
committed
feat(douyin): enhance image upload and publishing process
- Improved the image upload functionality by directly assigning files to the input element. - Added checks for the presence of necessary elements before proceeding with the upload. - Streamlined the process of filling in the title and content for the post. - Implemented a more reliable method for clicking the publish button.
1 parent 48e894f commit 246d0ad

File tree

1 file changed

+75
-126
lines changed

1 file changed

+75
-126
lines changed

src/sync/dynamic/douyin.ts

Lines changed: 75 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -32,142 +32,91 @@ export async function DynamicDouyin(data: SyncData) {
3232
});
3333
}
3434

35-
// 辅助函数:通过文本内容查找元素
36-
async function findElementByText(
37-
selector: string,
38-
text: string,
39-
maxRetries = 5,
40-
retryInterval = 1000,
41-
): Promise<Element | null> {
42-
for (let i = 0; i < maxRetries; i++) {
43-
const elements = document.querySelectorAll(selector);
44-
const element = Array.from(elements).find((element) => element.textContent?.includes(text));
45-
46-
if (element) {
47-
return element;
48-
}
49-
50-
console.log(`未找到包含文本 "${text}" 的元素,尝试次数:${i + 1}`);
51-
await new Promise((resolve) => setTimeout(resolve, retryInterval));
52-
}
53-
54-
console.error(`在 ${maxRetries} 次尝试后未找到包含文本 "${text}" 的元素`);
55-
return null;
35+
if (!images || images.length === 0) {
36+
alert('发布图文,请至少提供一张图片');
37+
return;
5638
}
5739

58-
async function checkImagesUploaded(expectedCount: number, maxRetries = 10, retryInterval = 3000): Promise<boolean> {
59-
for (let i = 0; i < maxRetries; i++) {
60-
const viewTexts = document.querySelectorAll('span:contains("查看")');
61-
const imageCount = viewTexts.length;
62-
63-
console.log(`当前找到 ${imageCount} 个 "查看" 文本,期望数量:${expectedCount}`);
64-
65-
if (imageCount === expectedCount) {
66-
console.log('图片上传完成');
67-
return true;
68-
}
69-
70-
console.log(`图片上传未完成,等待中...(尝试次数:${i + 1})`);
71-
await new Promise((resolve) => setTimeout(resolve, retryInterval));
72-
}
40+
await waitForElement('input[type="file"]');
41+
await new Promise((resolve) => setTimeout(resolve, 1000));
7342

74-
console.error(`在 ${maxRetries} 次尝试后,图片上传仍未完成`);
75-
return true;
43+
const semiTabs = document.querySelector('.semi-tabs.semi-tabs-top');
44+
console.debug('semitabs', semiTabs);
45+
if (!semiTabs || !semiTabs.previousElementSibling) {
46+
console.error('未找到 semitabs 或其前置元素');
47+
return;
7648
}
77-
78-
// 辅助函数:上传文件
79-
async function uploadImages() {
80-
const fileInput = (await waitForElement(
81-
'input[accept="image/png,image/jpeg,image/jpg,image/bmp,image/webp,image/tif"][multiple][type="file"]',
82-
)) as HTMLInputElement;
83-
if (!fileInput) {
84-
console.error('未找到文件输入元素');
85-
return;
86-
}
87-
88-
const dataTransfer = new DataTransfer();
89-
90-
for (const fileInfo of images) {
91-
try {
92-
const response = await fetch(fileInfo.url);
93-
if (!response.ok) {
94-
throw new Error(`HTTP 错误! 状态: ${response.status}`);
95-
}
96-
const blob = await response.blob();
97-
const file = new File([blob], fileInfo.name, { type: fileInfo.type });
98-
dataTransfer.items.add(file);
99-
} catch (error) {
100-
console.error(`上传图片 ${fileInfo.url} 失败:`, error);
101-
}
102-
}
103-
104-
if (dataTransfer.files.length > 0) {
105-
fileInput.files = dataTransfer.files;
106-
fileInput.dispatchEvent(new Event('change', { bubbles: true }));
107-
await new Promise((resolve) => setTimeout(resolve, 2000)); // 等待文件处理
108-
console.log('文件上传操作完成');
109-
} else {
110-
console.error('没有成功添加任何文件');
111-
}
49+
const tabsDiv = semiTabs.previousElementSibling.querySelectorAll('div');
50+
console.debug('tabsDiv', tabsDiv);
51+
const publishTab = Array.from(tabsDiv).find((e) => e.textContent === '发布图文');
52+
console.debug('publishTab', publishTab);
53+
if (!publishTab) {
54+
console.error('未找到 publishTab');
55+
return;
56+
}
57+
(publishTab as HTMLDivElement).click();
58+
await new Promise((resolve) => setTimeout(resolve, 1000));
59+
60+
const fileInput = document.querySelector(
61+
'input[accept="image/png,image/jpeg,image/jpg,image/bmp,image/webp,image/tif"]',
62+
) as HTMLInputElement;
63+
console.debug('fileInput', fileInput);
64+
if (!fileInput) {
65+
console.error('未找到 fileInput');
66+
return;
11267
}
11368

114-
await new Promise((resolve) => setTimeout(resolve, 2000));
115-
116-
if (images && images.length > 0) {
117-
// 上传文件
118-
await uploadImages();
119-
120-
// 填写标题
121-
const titleInput = (await waitForElement('input[placeholder="添加作品标题"]')) as HTMLInputElement;
122-
if (titleInput) {
123-
titleInput.value = title || content.slice(0, 20);
124-
titleInput.dispatchEvent(new Event('input', { bubbles: true }));
125-
}
126-
127-
// 填写内容
128-
const contentEditor = (await waitForElement('div[data-line-wrapper="true"]')) as HTMLDivElement;
129-
if (contentEditor) {
130-
// 创建一个新的 ClipboardEvent
131-
const pasteEvent = new ClipboardEvent('paste', {
132-
bubbles: true,
133-
cancelable: true,
134-
clipboardData: new DataTransfer(),
135-
});
136-
137-
// 设置剪贴板数据
138-
pasteEvent.clipboardData.setData('text/plain', content);
69+
const dataTransfer = new DataTransfer();
70+
for (const fileInfo of images) {
71+
console.debug('try upload file', fileInfo);
72+
const response = await fetch(fileInfo.url);
73+
const blob = await response.blob();
74+
const file = new File([blob], fileInfo.name, { type: fileInfo.type });
75+
dataTransfer.items.add(file);
76+
}
77+
fileInput.files = dataTransfer.files;
78+
const changeEvent = new Event('change', { bubbles: true });
79+
fileInput.dispatchEvent(changeEvent);
80+
const inputEvent = new Event('input', { bubbles: true });
81+
fileInput.dispatchEvent(inputEvent);
82+
console.debug('文件上传操作完成');
83+
84+
await waitForElement('input[placeholder="添加作品标题"]');
85+
const titleInput = document.querySelector('input[placeholder="添加作品标题"]') as HTMLInputElement;
86+
console.debug('titleInput', titleInput);
87+
if (titleInput) {
88+
titleInput.value = title || '';
89+
titleInput.dispatchEvent(new Event('input', { bubbles: true }));
90+
}
13991

140-
// 触发粘贴事件
141-
contentEditor.dispatchEvent(pasteEvent);
142-
}
92+
const contentEditor = document.querySelector(
93+
'div.zone-container.editor-kit-container.editor.editor-comp-publish[contenteditable="true"]',
94+
) as HTMLDivElement;
95+
if (contentEditor) {
96+
console.debug('descriptionInput', contentEditor);
97+
contentEditor.focus();
98+
const pasteEvent = new ClipboardEvent('paste', {
99+
bubbles: true,
100+
cancelable: true,
101+
clipboardData: new DataTransfer(),
102+
});
143103

144-
// // 等待内容更新
145-
await new Promise((resolve) => setTimeout(resolve, 3000));
104+
pasteEvent.clipboardData.setData('text/plain', content || '');
105+
contentEditor.dispatchEvent(pasteEvent);
106+
}
146107

147-
await checkImagesUploaded(images.length);
108+
await new Promise((resolve) => setTimeout(resolve, 5000));
148109

149-
if (data.isAutoPublish) {
150-
const maxAttempts = 3;
151-
for (let attempt = 0; attempt < maxAttempts; attempt++) {
152-
try {
153-
const publishButton = (await findElementByText('button', '发布', 5, 1000)) as HTMLButtonElement;
154-
if (publishButton) {
155-
publishButton.click();
156-
console.log('发布按钮已点击');
157-
await new Promise((resolve) => setTimeout(resolve, 3000));
158-
window.location.href = 'https://creator.douyin.com/creator-micro/content/manage';
159-
break; // 成功点击后退出循环
160-
} else {
161-
throw new Error('未找到发布按钮');
162-
}
163-
} catch (error) {
164-
console.warn(`第 ${attempt + 1} 次尝试查找发布按钮失败:`, error);
165-
if (attempt === maxAttempts - 1) {
166-
console.error('达到最大尝试次数,无法找到发布按钮');
167-
}
168-
await new Promise((resolve) => setTimeout(resolve, 2000)); // 等待2秒后重试
169-
}
170-
}
110+
if (data.isAutoPublish) {
111+
const buttons = document.querySelectorAll('button');
112+
const publishButton = Array.from(buttons).find((e) => e.textContent === '发布');
113+
if (publishButton) {
114+
console.debug('sendButton clicked');
115+
(publishButton as HTMLButtonElement).click();
116+
await new Promise((resolve) => setTimeout(resolve, 10000));
117+
window.location.href = 'https://creator.douyin.com/creator-micro/content/manage';
118+
} else {
119+
console.debug("未找到'发布'按钮");
171120
}
172121
}
173122
}

0 commit comments

Comments
 (0)