@@ -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