@@ -31,53 +31,38 @@ export async function DynamicZhihu(data: SyncData) {
3131 } ) ;
3232 }
3333
34- async function uploadFiles ( files : File [ ] ) {
35- const fileInput = ( await waitForElement ( 'input[type="file"][accept="image/*"]' ) ) as HTMLInputElement ;
36- if ( ! fileInput ) {
37- console . error ( '未找到文件输入元素' ) ;
38- return ;
39- }
40-
41- const dataTransfer = new DataTransfer ( ) ;
42- for ( const file of files ) {
43- if ( file . type . startsWith ( 'image/' ) ) {
44- dataTransfer . items . add ( file ) ;
45- } else {
46- console . warn ( `跳过非图片文件: ${ file . name } ` ) ;
47- }
48- }
49-
50- fileInput . files = dataTransfer . files ;
51- fileInput . dispatchEvent ( new Event ( 'change' , { bubbles : true } ) ) ;
52- fileInput . dispatchEvent ( new Event ( 'input' , { bubbles : true } ) ) ;
53-
54- console . debug ( '文件上传操作完成' ) ;
55- }
56-
5734 try {
58- // 等待并点击"写想法"元素
59- await waitForElement ( 'div.GlobalWriteV2-topTitle' ) ;
60- const writeThoughtButton = Array . from ( document . querySelectorAll ( 'div.GlobalWriteV2-topTitle' ) ) . find (
61- ( el ) => el . textContent ?. includes ( '写想法' ) ,
35+ await waitForElement ( 'input' ) ;
36+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
37+
38+ // 查找并点击"写想法"或"发想法"按钮
39+ const buttons = document . querySelectorAll ( 'button' ) ;
40+ const postButton = Array . from ( buttons ) . find (
41+ ( el ) => el . textContent ?. includes ( '写想法' ) || el . textContent ?. includes ( '发想法' ) ,
6242 ) ;
6343
64- if ( ! writeThoughtButton ) {
44+ if ( ! postButton ) {
6545 console . debug ( '未找到"写想法"元素' ) ;
6646 return ;
6747 }
6848
69- ( writeThoughtButton as HTMLElement ) . click ( ) ;
49+ console . debug ( 'postButton' , postButton ) ;
50+ postButton . click ( ) ;
7051 await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
7152
72- // 填写标题(如果有)
73- const titleInput = ( await waitForElement ( 'textarea[placeholder="添加标题(选填)"]' ) ) as HTMLTextAreaElement ;
53+ // 等待并填写标题
54+ await waitForElement ( 'textarea[placeholder="添加标题(选填)"]' ) ;
55+ const titleInput = document . querySelector ( 'textarea[placeholder="添加标题(选填)"]' ) as HTMLTextAreaElement ;
56+ console . debug ( 'titleInput' , titleInput ) ;
7457 if ( titleInput && title ) {
7558 titleInput . value = title ;
7659 titleInput . dispatchEvent ( new Event ( 'input' , { bubbles : true } ) ) ;
60+ titleInput . dispatchEvent ( new Event ( 'change' , { bubbles : true } ) ) ;
7761 }
7862
79- // 填写内容
80- const editorElement = ( await waitForElement ( 'div[data-contents="true"]' ) ) as HTMLDivElement ;
63+ // 查找编辑器并填写内容
64+ const editorElement = document . querySelector ( 'div[data-contents="true"]' ) as HTMLDivElement ;
65+ console . debug ( 'qlEditor' , editorElement ) ;
8166 if ( ! editorElement ) {
8267 console . debug ( '未找到编辑器元素' ) ;
8368 return ;
@@ -89,98 +74,66 @@ export async function DynamicZhihu(data: SyncData) {
8974 cancelable : true ,
9075 clipboardData : new DataTransfer ( ) ,
9176 } ) ;
92- pasteEvent . clipboardData . setData ( 'text/plain' , content || '' ) ;
77+ pasteEvent . clipboardData ? .setData ( 'text/plain' , content || '' ) ;
9378 editorElement . dispatchEvent ( pasteEvent ) ;
94- editorElement . dispatchEvent ( new Event ( 'input' , { bubbles : true } ) ) ;
95- editorElement . dispatchEvent ( new Event ( 'change' , { bubbles : true } ) ) ;
96-
9779 await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
9880
9981 // 处理图片上传
10082 if ( images && images . length > 0 ) {
101- const sendButton = Array . from ( document . querySelectorAll ( 'button' ) ) . find ( ( el ) => el . textContent ?. includes ( '发布' ) ) ;
102-
103- if ( sendButton ) {
104- const uploadButton = sendButton . parentElement ?. previousElementSibling ?. children [ 1 ] as HTMLElement ;
105- if ( uploadButton ) {
106- uploadButton . click ( ) ;
107- await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
108-
109- await waitForElement ( 'input[type="file"][accept="image/*"]' ) ;
110- const fileInput = document . querySelector ( 'input[type="file"][accept="image/*"]' ) as HTMLInputElement ;
111- if ( fileInput ) {
112- const imageFiles = await Promise . all (
113- images . map ( async ( file ) => {
114- const response = await fetch ( file . url ) ;
115- const blob = await response . blob ( ) ;
116- return new File ( [ blob ] , file . name , { type : file . type } ) ;
117- } ) ,
118- ) ;
119- await uploadFiles ( imageFiles ) ;
120-
121- // 等待图片上传完成
122- for ( let i = 0 ; i < 30 ; i ++ ) {
123- const uploadedCountElement = document . evaluate (
124- "//*[contains(text(), '已上传')]" ,
125- document ,
126- null ,
127- XPathResult . FIRST_ORDERED_NODE_TYPE ,
128- null ,
129- ) . singleNodeValue as HTMLElement ;
130-
131- if ( uploadedCountElement ) {
132- const match = uploadedCountElement . textContent ?. match ( / 已 上 传 ( \d + ) 张 图 片 / ) ;
133- if ( match && parseInt ( match [ 1 ] ) >= images . length ) {
134- console . debug ( `图片上传完成:${ match [ 1 ] } 张` ) ;
135- break ;
136- }
137- }
138- await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
139- }
140-
141- const insertButton = Array . from ( document . querySelectorAll ( 'button' ) ) . find (
142- ( el ) => el . textContent ?. includes ( '插入图片' ) ,
143- ) ;
144- if ( insertButton ) {
145- insertButton . click ( ) ;
146- }
147- }
83+ for ( let i = 0 ; i < images . length ; i ++ ) {
84+ const image = images [ i ] ;
85+ if ( i >= 9 ) {
86+ console . debug ( 'Zhihu 最多支持 9 张,跳过' ) ;
87+ break ;
14888 }
89+ console . debug ( 'try upload file' , image ) ;
90+ const response = await fetch ( image . url ) ;
91+ const arrayBuffer = await response . arrayBuffer ( ) ;
92+ const file = new File ( [ arrayBuffer ] , image . name , { type : image . type } ) ;
93+
94+ const imagePasteEvent = new ClipboardEvent ( 'paste' , {
95+ bubbles : true ,
96+ cancelable : true ,
97+ clipboardData : new DataTransfer ( ) ,
98+ } ) ;
99+ imagePasteEvent . clipboardData ?. items . add ( file ) ;
100+ editorElement . dispatchEvent ( imagePasteEvent ) ;
149101 }
150102 }
151103
152- // 发布内容
153- if ( data . isAutoPublish ) {
154- const maxRetries = 3 ;
155- const retryInterval = 2000 ; // 2秒
156-
157- const attemptPublish = async ( ) : Promise < boolean > => {
158- const publishButton = Array . from ( document . querySelectorAll ( 'button' ) ) . find (
159- ( el ) => el . textContent ?. includes ( '发布' ) ,
160- ) ;
161- if ( publishButton ) {
162- console . debug ( '发布按钮被点击' ) ;
163- publishButton . click ( ) ;
164- return true ;
165- }
166- return false ;
167- } ;
168-
169- let isPublished = false ;
170- for ( let i = 0 ; i < maxRetries ; i ++ ) {
171- isPublished = await attemptPublish ( ) ;
172- if ( isPublished ) {
173- await new Promise ( ( resolve ) => setTimeout ( resolve , 3000 ) ) ;
174- window . location . reload ( ) ;
175- break ;
176- }
177- console . debug ( `未找到"发布"按钮,重试第 ${ i + 1 } 次` ) ;
178- await new Promise ( ( resolve ) => setTimeout ( resolve , retryInterval ) ) ;
179- }
104+ editorElement . dispatchEvent ( new Event ( 'input' , { bubbles : true } ) ) ;
105+ editorElement . dispatchEvent ( new Event ( 'change' , { bubbles : true } ) ) ;
106+ await new Promise ( ( resolve ) => setTimeout ( resolve , 3000 ) ) ;
107+
108+ // 等待图片上传完成(检查是否有 blob 图片正在加载)
109+ let loadingCount = 0 ;
110+ while ( loadingCount < 30 ) {
111+ const uploadingImages = document . querySelectorAll ( 'div.DraggableTags-tag-drag img' ) ;
112+ if ( uploadingImages . length === 0 ) break ;
113+
114+ const loadingImg = Array . from ( uploadingImages ) . find ( ( img ) => ( img as HTMLImageElement ) . src . startsWith ( 'blob' ) ) ;
115+ console . debug ( 'loadingImg' , loadingImg ) ;
116+ if ( ! loadingImg ) break ;
180117
181- if ( ! isPublished ) {
182- console . error ( `在 ${ maxRetries } 次尝试后仍未能发布内容` ) ;
118+ await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) ;
119+ loadingCount ++ ;
120+ }
121+
122+ // 发布内容
123+ const allButtons = document . querySelectorAll ( 'button' ) ;
124+ const sendButton = Array . from ( allButtons ) . find ( ( el ) => el . textContent ?. includes ( '发布' ) ) ;
125+ console . debug ( 'sendButton' , sendButton ) ;
126+
127+ if ( sendButton ) {
128+ if ( data . isAutoPublish ) {
129+ console . debug ( 'sendButton clicked' ) ;
130+ const clickEvent = new Event ( 'click' , { bubbles : true } ) ;
131+ sendButton . dispatchEvent ( clickEvent ) ;
132+ await new Promise ( ( resolve ) => setTimeout ( resolve , 3000 ) ) ;
133+ window . location . href = 'https://www.zhihu.com/follow' ;
183134 }
135+ } else {
136+ console . debug ( '未找到"发送"按钮' ) ;
184137 }
185138
186139 console . debug ( '成功填入知乎内容和图片' ) ;
0 commit comments