@@ -9,20 +9,243 @@ function truncate(str, n) {
9
9
return subString [ 0 ] . slice ( 0 , subString [ 0 ] . lastIndexOf ( '.' ) + 1 ) ; // find nearest end of sentence
10
10
}
11
11
12
+ // Function to get the correct input selector
13
+ async function getInputSelector ( page ) {
14
+ const placeholderText = 'To rewrite text, enter or paste it here and press "Paraphrase."' ;
15
+ const inputSelectors = [
16
+ '#inputText' ,
17
+ '#paraphraser-input-box' ,
18
+ `div[placeholder="${ placeholderText } "]` ,
19
+ ] ;
20
+
21
+ for ( const selector of inputSelectors ) {
22
+ const exists = await page . $ ( selector ) !== null ;
23
+ if ( exists ) {
24
+ return selector ; // Return the selector if found
25
+ }
26
+ }
27
+
28
+ console . error ( 'Error: Unable to find a valid input selector.' ) ;
29
+ return null ; // Return null if no valid selector is found
30
+ }
31
+
32
+ // Function to get the input field using the provided selector
33
+ async function getInputField ( page , inputSelector ) {
34
+ if ( ! inputSelector ) {
35
+ return null ; // Return null if the inputSelector is not provided
36
+ }
37
+
38
+ try {
39
+ const input = await page . waitForSelector ( inputSelector , { visible : true , timeout : 5000 } ) ;
40
+ return input ; // Return the input field if found
41
+ } catch ( error ) {
42
+ console . error ( `Error: Unable to find the input field with the selector: ${ inputSelector } ` ) ;
43
+ return null ; // Return null if the input field is not found
44
+ }
45
+ }
46
+
47
+ // Function to clear the input field
48
+ async function clearInputField ( page , inputSelector , inputField ) {
49
+ await inputField . click ( ) ;
50
+ await inputField . type ( ' ' ) ;
51
+
52
+ // Clear the text area using JavaScript
53
+ await page . evaluate ( ( selector ) => {
54
+ const inputElement = document . querySelector ( selector ) ;
55
+ if ( inputElement ) {
56
+ inputElement . textContent = '' ;
57
+ if ( inputElement . value ) {
58
+ inputElement . value = '' ; // Clear value for input elements
59
+ }
60
+ }
61
+ } , inputSelector ) ;
62
+ // console.log('Input cleared using JavaScript');
63
+
64
+ // Additional step to ensure complete clearing using keyboard commands
65
+ await page . focus ( inputSelector ) ;
66
+ await page . keyboard . down ( 'Control' ) ;
67
+ await page . keyboard . press ( 'KeyA' ) ;
68
+ await page . keyboard . up ( 'Control' ) ;
69
+ await page . keyboard . press ( 'Backspace' ) ; // Using 'Backspace' instead of 'Delete' for broader compatibility
70
+ // console.log('Input cleared using keyboard commands');
71
+ }
72
+
73
+ // Function to get inputContent
74
+ function getInputContent ( page , inputSelector ) {
75
+ return page . evaluate ( ( selector ) => {
76
+ const inputElement = document . querySelector ( selector ) ;
77
+ if ( inputElement ) {
78
+ return inputElement . textContent ;
79
+ }
80
+ return null ;
81
+ } , inputSelector ) ;
82
+ }
83
+
84
+ // Function to input text into the specified field
85
+ async function inputString ( page , inputSelector , inputField , text ) {
86
+ // Attempt to change textContent directly using JavaScript
87
+ await page . evaluate ( ( selector , textString ) => {
88
+ const inputElement = document . querySelector ( selector ) ;
89
+ if ( inputElement ) {
90
+ inputElement . textContent = textString ;
91
+ if ( inputElement . value !== undefined ) {
92
+ inputElement . value = textString ; // For input elements
93
+ }
94
+ }
95
+ } , inputSelector , text ) ;
96
+
97
+ // Attempt to set clipboard content and paste it
98
+ await page . evaluate ( async ( textString ) => {
99
+ // eslint-disable-next-line no-undef
100
+ await navigator . clipboard . writeText ( textString ) ;
101
+ } , text ) ;
102
+ await page . focus ( inputSelector ) ;
103
+ await page . keyboard . down ( 'Control' ) ;
104
+ await page . keyboard . press ( 'KeyV' ) ;
105
+ await page . keyboard . up ( 'Control' ) ;
106
+
107
+ const inputContent = await getInputContent ( page , inputSelector ) ;
108
+ if ( inputContent !== text ) {
109
+ // Attempt to type it out
110
+ inputField . type ( text ) ;
111
+ }
112
+ }
113
+
114
+ // Function to get the correct button selector
115
+ async function getButtonSelector ( page ) {
116
+ const buttonSelectors = [
117
+ 'button.quillArticleBtn' ,
118
+ '[aria-label="Rephrase (Cmd + Return)"] button' ,
119
+ '[aria-label="Paraphrase (Cmd + Return)"] button' ,
120
+ "//div[contains(text(), 'Paraphrase') or contains(text(), 'Rephrase')]/ancestor::button" ,
121
+ ] ;
122
+
123
+ for ( const selector of buttonSelectors ) {
124
+ let exists ;
125
+ if ( selector . startsWith ( '//' ) ) { // XPath selector
126
+ exists = await page . $x ( selector ) . length > 0 ;
127
+ } else { // CSS selector
128
+ exists = await page . $ ( selector ) !== null ;
129
+ }
130
+ if ( exists ) {
131
+ return selector ; // Return the selector if found
132
+ }
133
+ }
134
+
135
+ console . error ( 'Error: Unable to find a valid button selector.' ) ;
136
+ return null ; // Return null if no valid selector is found
137
+ }
138
+
139
+ // Function to click the appropriate button
140
+ async function clickParaphraseButton ( page , buttonSelector ) {
141
+ if ( ! buttonSelector ) {
142
+ return false ; // Return false if the buttonSelector is not provided
143
+ }
144
+
145
+ let button ;
146
+ if ( buttonSelector . startsWith ( '//' ) ) { // XPath selector
147
+ const [ firstButton ] = await page . $x ( buttonSelector ) ;
148
+ button = firstButton ;
149
+ } else { // CSS selector
150
+ button = await page . $ ( buttonSelector ) ;
151
+ }
152
+
153
+ if ( button ) {
154
+ await button . click ( ) ;
155
+ return true ;
156
+ }
157
+ return false ;
158
+ }
159
+
160
+ // Function to check if the form is submitted
161
+ async function waitForFormSubmission ( page , buttonSelector ) {
162
+ try {
163
+ // Wait for paraphrasing to complete - button to become enabled
164
+ // await page.waitForSelector(`${buttonSelector}:not([disabled])`);
165
+
166
+ // await second div in buttonSelector to be removed from dom
167
+ // await page.waitForSelector(`${buttonSelector} div:nth-child(2)`, { hidden: true });
168
+
169
+ // Implement the logic to check if the form is submitted
170
+ // const isDisabled = await page.$eval(buttonSelector, (button) => button.disabled);
171
+ // return isDisabled;
172
+
173
+ // Wait for the new div to appear within the button, indicating the process has started
174
+ await page . waitForSelector ( `${ buttonSelector } div:nth-child(2)` , { visible : true } ) ;
175
+
176
+ // Then, wait for the new div to disappear, indicating the process has finished
177
+ await page . waitForSelector ( `${ buttonSelector } div:nth-child(2)` , { hidden : true } ) ;
178
+
179
+ return true ;
180
+ } catch ( error ) {
181
+ console . error ( 'Error: Process did not complete in the expected time.' ) ;
182
+ return false ;
183
+ }
184
+ }
185
+
186
+ // Function to submit the form
187
+ async function submitForm ( page , buttonSelector ) {
188
+ /*
189
+ // Try submitting the form using keyboard shortcut
190
+ await page.focus(inputSelector);
191
+ await page.keyboard.down('Control');
192
+ await page.keyboard.press('Enter');
193
+ await page.keyboard.up('Control');
194
+
195
+ // Check if the form submits
196
+ const isSubmitted = await isProcessComplete(page, buttonSelector);
197
+ if (isSubmitted) {
198
+ return true;
199
+ }
200
+ */
201
+
202
+ // Try clicking the paraphrase button as a fallback
203
+ const isClicked = await clickParaphraseButton ( page , buttonSelector ) ;
204
+ if ( ! isClicked ) {
205
+ console . log ( 'Failed to find and click the paraphrase button.' ) ;
206
+ return false ;
207
+ }
208
+
209
+ const isSubmitted = await waitForFormSubmission ( page , buttonSelector ) ;
210
+ if ( ! isSubmitted ) {
211
+ return false ;
212
+ }
213
+
214
+ return true ;
215
+ }
216
+
217
+ // Function to get the output content
218
+ async function getOutputContent ( page , outputSelector ) {
219
+ try {
220
+ const content = await page . evaluate ( ( selector ) => {
221
+ const element = document . querySelector ( selector ) ;
222
+ return element ? element . textContent : null ;
223
+ } , outputSelector ) ;
224
+
225
+ if ( content === null ) {
226
+ console . log ( 'Output element not found or no content.' ) ;
227
+ return null ;
228
+ }
229
+
230
+ return content ;
231
+ } catch ( error ) {
232
+ console . error ( 'Error retrieving output content:' , error ) ;
233
+ return null ;
234
+ }
235
+ }
236
+
12
237
async function quillbot ( text ) {
238
+ let browser ; // Declare browser outside of try-catch so it's accessible in finally
13
239
try {
14
- // const inputSelector = 'div#inputText';
15
- // const inputSelector = 'div#paraphraser-input-box';
16
- const placeholderText = 'To rewrite text, enter or paste it here and press Paraphrase.' ;
17
- const inputSelector = `div[placeholder="${ placeholderText } "]` ;
18
- const buttonSelector = 'button.quillArticleBtn' ;
19
- const outputSelector = 'div#paraphraser-output-box' ;
240
+ const outputSelector = '#paraphraser-output-box' ;
241
+
20
242
const numberOfCharacters = 125 ;
21
243
let str = text . trim ( ) ;
22
244
const parts = [ ] ;
23
245
let output = '' ;
24
246
25
247
// 125 words per paraphrase for a free account
248
+ // So break up the text into parts of 125 words
26
249
if ( str . match ( / ( \w + ) / g) . length > numberOfCharacters ) {
27
250
while ( str . match ( / ( \w + ) / g) . length > numberOfCharacters ) {
28
251
const part = truncate ( str , numberOfCharacters ) . trim ( ) ;
@@ -34,81 +257,79 @@ async function quillbot(text) {
34
257
parts . push ( str ) ;
35
258
}
36
259
37
- const browser = await puppeteer . launch ( { headless : true } ) ;
260
+ browser = await puppeteer . launch ( {
261
+ // headless: 'new',
262
+ headless : false ,
263
+ } ) ;
38
264
39
265
const page = await browser . newPage ( ) ;
40
266
await page . goto ( 'https://quillbot.com/' , { waitUntil : 'networkidle0' } ) ;
41
267
42
268
// Wait for input
43
- const input = await page . waitForSelector ( inputSelector ) ;
269
+ const inputSelector = await getInputSelector ( page ) ;
270
+ const inputField = await getInputField ( page , inputSelector ) ;
271
+ if ( ! inputField ) {
272
+ // Handle the case where the input field wasn't found
273
+ console . log ( 'Input field not found. Exiting script.' ) ;
274
+ return ; // Exit the function, browser will be closed in finally
275
+ }
44
276
console . log ( 'Input found' ) ;
45
277
278
+ // Go through each part and paraphrase it
46
279
for ( let i = 0 ; i < parts . length ; i += 1 ) {
47
280
console . log ( 'Paraphrasing part' , i + 1 , 'of' , parts . length ) ;
48
281
49
282
const part = parts [ i ] ;
50
283
51
- // await page.evaluate((selector) => {
52
- // document.querySelector(selector).textContent = '';
53
- // }, inputSelector);
284
+ // eslint-disable-next-line no-promise-executor-return
285
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
286
+
287
+ // Clear the text area
288
+ await clearInputField ( page , inputSelector , inputField ) ;
54
289
55
- // Input the string in the text area
56
- /* await page.evaluate((selector, text) => {
57
- document.querySelector(selector).textContent = text;
58
- }, inputSelector, part); */
59
- // await input.type(part);
60
- // await page.focus(inputSelector);
61
290
// eslint-disable-next-line no-promise-executor-return
62
- await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
63
- await input . click ( ) ;
64
- await input . type ( ' ' ) ;
291
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
292
+
293
+ // Input the string in the text area
294
+ await inputString ( page , inputSelector , inputField , part ) ;
295
+
65
296
// eslint-disable-next-line no-promise-executor-return
66
- await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
67
-
68
- await page . keyboard . down ( 'Control' ) ;
69
- await page . keyboard . press ( 'KeyA' ) ;
70
- await page . keyboard . up ( 'Control' ) ;
71
- await page . keyboard . up ( 'Delete' ) ;
72
- // Set clipboard content
73
- // eslint-disable-next-line no-loop-func
74
- await page . evaluate ( async ( textString ) => {
75
- // eslint-disable-next-line no-undef
76
- await navigator . clipboard . writeText ( textString ) ;
77
- } , part ) ;
78
- // await clipboardy.write(part);
79
- await page . keyboard . down ( 'Control' ) ;
80
- await page . keyboard . press ( 'KeyV' ) ;
81
- await page . keyboard . up ( 'Control' ) ;
82
- // await input.type(' ');
83
-
84
- // Generate the result
85
- await page . click ( buttonSelector ) ;
86
-
87
- // wait for paraphrasing to complete - button to become enabled
88
- // await page.waitForSelector(`${buttonSelector}:not([disabled])`);
89
- // await second div in buttonSelector to be removed from dom
90
- await page . waitForSelector ( `${ buttonSelector } div:nth-child(2)` , { hidden : true } ) ;
91
- console . log ( 'Paraphrasing complete' ) ;
92
-
93
- const paraphrased = await page . evaluate (
94
- ( selector ) => document . querySelector ( selector ) . textContent ,
95
- outputSelector ,
96
- ) ;
97
-
98
- output += paraphrased ;
99
- }
297
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
100
298
101
- console . log ( 'Paraphrased:' ) ;
102
- console . log ( output ) ; // Display result
299
+ const buttonSelector = await getButtonSelector ( page ) ;
103
300
104
- // await new Promise((resolve) => setTimeout(resolve, 20000));
301
+ const isSubmitted = await submitForm ( page , buttonSelector ) ;
302
+ if ( ! isSubmitted ) {
303
+ // Handle submission failure
304
+ console . log ( 'Form submission failed. Exiting script.' ) ;
305
+ return ;
306
+ }
105
307
106
- browser . close ( ) ;
308
+ // Get the paraphrased content
309
+ const outputContent = await getOutputContent ( page , outputSelector ) ;
310
+ if ( outputContent ) {
311
+ output += outputContent ;
312
+ } else {
313
+ // Handle the case where no output content is retrieved
314
+ console . log ( 'Output content not found. Exiting script.' ) ;
315
+ return ;
316
+ }
107
317
318
+ console . log ( 'Paraphrasing complete' , i + 1 , 'of' , parts . length ) ;
319
+
320
+ // eslint-disable-next-line no-promise-executor-return
321
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
322
+ }
323
+
324
+ console . log ( 'Paraphrasing complete' ) ;
108
325
return output ;
109
326
} catch ( error ) {
110
327
console . log ( `Error: ${ error } ` ) ;
111
328
return null ;
329
+ } finally {
330
+ if ( browser ) {
331
+ await browser . close ( ) ;
332
+ }
112
333
}
113
334
}
114
335
0 commit comments