@kudoai/chatgpt.js 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -8
- package/chatgpt.js +91 -89
- package/dist/chatgpt.min.js +10 -4
- package/docs/README.md +7 -8
- package/docs/USERGUIDE.md +3 -3
- package/package.json +2 -2
- package/starters/chrome/extension/lib/chatgpt.js +91 -89
- package/starters/chrome/extension/manifest.json +1 -1
- package/starters/greasemonkey/chatgpt.js-greasemonkey-starter.user.js +4 -4
|
@@ -85,9 +85,10 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
85
85
|
document.head.append(modalStyle);
|
|
86
86
|
}
|
|
87
87
|
modalStyle.innerText = ( // update prev/new style contents
|
|
88
|
+
'.no-mobile-tap-outline { outline: none ; -webkit-tap-highlight-color: transparent }'
|
|
88
89
|
|
|
89
90
|
// Background styles
|
|
90
|
-
'.chatgpt-modal {'
|
|
91
|
+
+ '.chatgpt-modal {'
|
|
91
92
|
+ 'position: fixed ; top: 0 ; left: 0 ; width: 100% ; height: 100% ;' // expand to full view-port
|
|
92
93
|
+ 'background-color: rgba(67, 70, 72, 0) ;' // init dim bg but no opacity
|
|
93
94
|
+ 'transition: background-color 0.05s ease ;' // speed to transition in show alert routine
|
|
@@ -148,7 +149,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
148
149
|
|
|
149
150
|
// Create/append buttons (if provided) to buttons div
|
|
150
151
|
const modalButtons = document.createElement('div');
|
|
151
|
-
modalButtons.classList.add('modal-buttons');
|
|
152
|
+
modalButtons.classList.add('modal-buttons', 'no-mobile-tap-outline');
|
|
152
153
|
if (btns) { // are supplied
|
|
153
154
|
if (!Array.isArray(btns)) btns = [btns]; // convert single button to array if necessary
|
|
154
155
|
btns.forEach((buttonFn) => { // create title-cased labels + attach listeners
|
|
@@ -157,7 +158,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
157
158
|
.replace(/[_-]\w/g, match => match.slice(1).toUpperCase()) // convert snake/kebab to camel case
|
|
158
159
|
.replace(/([A-Z])/g, ' $1') // insert spaces
|
|
159
160
|
.replace(/^\w/, firstChar => firstChar.toUpperCase()); // capitalize first letter
|
|
160
|
-
button.
|
|
161
|
+
button.onclick = () => { dismissAlert(); buttonFn(); };
|
|
161
162
|
modalButtons.insertBefore(button, modalButtons.firstChild); // insert button to left
|
|
162
163
|
});
|
|
163
164
|
}
|
|
@@ -177,12 +178,11 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
177
178
|
const checkboxFn = checkbox, // assign the named function to checkboxFn
|
|
178
179
|
checkboxInput = document.createElement('input');
|
|
179
180
|
checkboxInput.type = 'checkbox';
|
|
180
|
-
checkboxInput.
|
|
181
|
+
checkboxInput.onchange = checkboxFn;
|
|
181
182
|
|
|
182
183
|
// Create/show label
|
|
183
184
|
const checkboxLabel = document.createElement('label');
|
|
184
|
-
checkboxLabel.
|
|
185
|
-
checkboxInput.checked = !checkboxInput.checked; checkboxFn(); });
|
|
185
|
+
checkboxLabel.onclick = () => { checkboxInput.checked = !checkboxInput.checked; checkboxFn(); };
|
|
186
186
|
checkboxLabel.textContent = checkboxFn.name.charAt(0).toUpperCase() // capitalize first char
|
|
187
187
|
+ checkboxFn.name.slice(1) // format remaining chars
|
|
188
188
|
.replace(/([A-Z])/g, (match, letter) => ' ' + letter.toLowerCase()) // insert spaces, convert to lowercase
|
|
@@ -194,7 +194,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
194
194
|
|
|
195
195
|
// Create close button
|
|
196
196
|
const closeBtn = document.createElement('div');
|
|
197
|
-
closeBtn.title = 'Close'; closeBtn.classList.add('modal-close-btn');
|
|
197
|
+
closeBtn.title = 'Close'; closeBtn.classList.add('modal-close-btn', 'no-mobile-tap-outline');
|
|
198
198
|
const closeSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
199
199
|
closeSVG.setAttribute('height', '10px');
|
|
200
200
|
closeSVG.setAttribute('viewBox', '0 0 14 14');
|
|
@@ -247,8 +247,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
247
247
|
|
|
248
248
|
// Add listeners to dismiss alert
|
|
249
249
|
const dismissElems = [modalContainer, closeBtn, closeSVG, dismissBtn];
|
|
250
|
-
dismissElems.forEach(elem =>
|
|
251
|
-
elem.addEventListener('click', clickHandler); });
|
|
250
|
+
dismissElems.forEach(elem => elem.onclick = clickHandler);
|
|
252
251
|
document.addEventListener('keydown', keyHandler);
|
|
253
252
|
|
|
254
253
|
// Define alert dismisser
|
|
@@ -262,10 +261,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
262
261
|
alertQueue = JSON.parse(localStorage.alertQueue);
|
|
263
262
|
alertQueue.shift(); // + memory
|
|
264
263
|
localStorage.alertQueue = JSON.stringify(alertQueue); // + storage
|
|
265
|
-
|
|
266
|
-
// Remove all listeners to prevent memory leaks
|
|
267
|
-
dismissElems.forEach(elem => { elem.removeEventListener('click', clickHandler); });
|
|
268
|
-
document.removeEventListener('keydown', keyHandler);
|
|
264
|
+
document.removeEventListener('keydown', keyHandler); // prevent memory leaks
|
|
269
265
|
|
|
270
266
|
// Check for pending alerts in queue
|
|
271
267
|
if (alertQueue.length > 0) {
|
|
@@ -282,7 +278,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
282
278
|
return modalContainer.id; // if assignment used
|
|
283
279
|
},
|
|
284
280
|
|
|
285
|
-
|
|
281
|
+
async askAndGetReply(query) {
|
|
286
282
|
chatgpt.send(query); await chatgpt.isIdle();
|
|
287
283
|
return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest');
|
|
288
284
|
},
|
|
@@ -300,8 +296,10 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
300
296
|
const randomDelay = Math.max(2, Math.floor(chatgpt.randomFloat() * 21 - 10)); // set random delay up to ±10 secs
|
|
301
297
|
autoRefresh.isActive = setTimeout(() => {
|
|
302
298
|
const manifestScript = document.querySelector('script[src*="_ssgManifest.js"]');
|
|
303
|
-
|
|
304
|
-
|
|
299
|
+
if (manifestScript) {
|
|
300
|
+
document.querySelector('#refresh-frame').src = manifestScript.src + '?' + Date.now();
|
|
301
|
+
console.log('↻ ChatGPT >> [' + autoRefresh.nowTimeStamp() + '] ChatGPT session refreshed');
|
|
302
|
+
}
|
|
305
303
|
scheduleRefreshes(interval);
|
|
306
304
|
}, (interval + randomDelay) * 1000);
|
|
307
305
|
};
|
|
@@ -309,8 +307,8 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
309
307
|
console.log('↻ ChatGPT >> [' + chatgpt.autoRefresh.nowTimeStamp() + '] Auto refresh activated');
|
|
310
308
|
|
|
311
309
|
// Add listener to send beacons in Chromium to thwart auto-discards if Page Visibility API supported
|
|
312
|
-
if (navigator.userAgent.includes('Chrome') && typeof document.hidden !== 'undefined')
|
|
313
|
-
document.addEventListener('visibilitychange', this.toggle.beacons);
|
|
310
|
+
if (navigator.userAgent.includes('Chrome') && typeof document.hidden !== 'undefined')
|
|
311
|
+
document.addEventListener('visibilitychange', this.toggle.beacons);
|
|
314
312
|
},
|
|
315
313
|
|
|
316
314
|
deactivate() {
|
|
@@ -379,7 +377,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
379
377
|
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); }
|
|
380
378
|
},
|
|
381
379
|
|
|
382
|
-
|
|
380
|
+
async clearChats() { // back-end method
|
|
383
381
|
return new Promise((resolve, reject) => {
|
|
384
382
|
chatgpt.getAccessToken().then(token => {
|
|
385
383
|
const xhr = new XMLHttpRequest();
|
|
@@ -398,7 +396,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
398
396
|
code: {
|
|
399
397
|
// Tip: Use template literals for easier passing of code arguments. Ensure backticks and `$`s are escaped (using `\`)
|
|
400
398
|
|
|
401
|
-
|
|
399
|
+
async execute(code) {
|
|
402
400
|
if (!code) return console.error('Code argument not supplied. Pass some code!');
|
|
403
401
|
if (typeof code !== 'string') return console.error('Code argument must be a string!');
|
|
404
402
|
chatgpt.send('Display the output as if you were terminal:\n\n' + code);
|
|
@@ -412,7 +410,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
412
410
|
return codeBlocks ? codeBlocks[codeBlocks.length - 1] : msg;
|
|
413
411
|
},
|
|
414
412
|
|
|
415
|
-
|
|
413
|
+
async isIdle() {
|
|
416
414
|
await new Promise(resolve => { // when in conversation page
|
|
417
415
|
(function checkConvoPage() {
|
|
418
416
|
document.querySelector('div[data-message-author-role]') ? resolve(true)
|
|
@@ -421,26 +419,26 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
421
419
|
await new Promise(resolve => { // when reply starts generating
|
|
422
420
|
(function checkReplyExists() {
|
|
423
421
|
const msgDivs = document.querySelectorAll('div[data-message-author-role]');
|
|
424
|
-
msgDivs[msgDivs.length - 1]
|
|
422
|
+
msgDivs[msgDivs.length - 1]?.dataset.messageAuthorRole == 'assistant' ? resolve(true)
|
|
425
423
|
: setTimeout(checkReplyExists, 200); })();
|
|
426
424
|
});
|
|
427
425
|
const lastReplyDiv = await new Promise(resolve => { // when code starts generating
|
|
428
426
|
(function checkPreExists() {
|
|
429
427
|
const replyDivs = document.querySelectorAll('div[data-message-author-role="assistant"]'),
|
|
430
428
|
lastReplyDiv = replyDivs[replyDivs.length - 1];
|
|
431
|
-
lastReplyDiv
|
|
429
|
+
lastReplyDiv?.querySelector('pre') ? resolve(lastReplyDiv)
|
|
432
430
|
: setTimeout(checkPreExists, 200); })();
|
|
433
431
|
});
|
|
434
432
|
return Promise.race([
|
|
435
433
|
new Promise(resolve => { // when code block not last child of reply div
|
|
436
434
|
(function checkPreNotLast() {
|
|
437
|
-
lastReplyDiv
|
|
435
|
+
lastReplyDiv?.querySelector('pre').nextElementSibling ? resolve(true)
|
|
438
436
|
: setTimeout(checkPreNotLast, 200); })();
|
|
439
437
|
}), chatgpt.isIdle() // ...or reply stopped generating
|
|
440
438
|
]);
|
|
441
439
|
},
|
|
442
440
|
|
|
443
|
-
|
|
441
|
+
async minify(code) {
|
|
444
442
|
if (!code) return console.error('Code argument not supplied. Pass some code!');
|
|
445
443
|
if (typeof code !== 'string') return console.error('Code argument must be a string!');
|
|
446
444
|
chatgpt.send('Minify the following code:\n\n' + code);
|
|
@@ -449,7 +447,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
449
447
|
return chatgpt.code.extract(await chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'));
|
|
450
448
|
},
|
|
451
449
|
|
|
452
|
-
|
|
450
|
+
async obfuscate(code) {
|
|
453
451
|
if (!code) return console.error('Code argument not supplied. Pass some code!');
|
|
454
452
|
if (typeof code !== 'string') return console.error('Code argument must be a string!');
|
|
455
453
|
chatgpt.send('Obfuscate the following code:\n\n' + code);
|
|
@@ -458,7 +456,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
458
456
|
return chatgpt.code.extract(await chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'));
|
|
459
457
|
},
|
|
460
458
|
|
|
461
|
-
|
|
459
|
+
async refactor(code, objective) {
|
|
462
460
|
if (!code) return console.error('Code (1st) argument not supplied. Pass some code!');
|
|
463
461
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
464
462
|
return console.error(`Argument ${ i + 1 } must be a string.`);
|
|
@@ -468,7 +466,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
468
466
|
return chatgpt.code.extract(await chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'));
|
|
469
467
|
},
|
|
470
468
|
|
|
471
|
-
|
|
469
|
+
async review(code) {
|
|
472
470
|
if (!code) return console.error('Code argument not supplied. Pass some code!');
|
|
473
471
|
if (typeof code !== 'string') return console.error('Code argument must be a string!');
|
|
474
472
|
chatgpt.send('Review the following code for me:\n\n' + code);
|
|
@@ -477,7 +475,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
477
475
|
return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest');
|
|
478
476
|
},
|
|
479
477
|
|
|
480
|
-
|
|
478
|
+
async unminify(code) {
|
|
481
479
|
if (!code) return console.error('Code argument not supplied. Pass some code!');
|
|
482
480
|
if (typeof code !== 'string') return console.error('Code argument must be a string!');
|
|
483
481
|
chatgpt.send('Unminify the following code.:\n\n' + code);
|
|
@@ -486,7 +484,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
486
484
|
return chatgpt.code.extract(await chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'));
|
|
487
485
|
},
|
|
488
486
|
|
|
489
|
-
|
|
487
|
+
async write(prompt, outputLang) {
|
|
490
488
|
if (!prompt) return console.error('Prompt (1st) argument not supplied. Pass a prompt!');
|
|
491
489
|
if (!outputLang) return console.error('outputLang (2nd) argument not supplied. Pass a language!');
|
|
492
490
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
@@ -500,7 +498,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
500
498
|
|
|
501
499
|
continue() { chatgpt.response.continue(); },
|
|
502
500
|
|
|
503
|
-
|
|
501
|
+
async detectLanguage(text) {
|
|
504
502
|
if (!text) return console.error('Text argument not supplied. Pass some text!');
|
|
505
503
|
if (typeof text !== 'string') return console.error('Text argument must be a string!');
|
|
506
504
|
chatgpt.send('Detect the language of the following text:\n\n' + text
|
|
@@ -512,7 +510,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
512
510
|
|
|
513
511
|
executeCode() { chatgpt.code.execute(); },
|
|
514
512
|
|
|
515
|
-
|
|
513
|
+
async exportChat(chatToGet, format) {
|
|
516
514
|
// chatToGet = 'active' (default) | 'latest' | index|title|id of chat to get
|
|
517
515
|
// format = 'html' (default) | 'md' | 'pdf' | 'text'
|
|
518
516
|
|
|
@@ -544,9 +542,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
544
542
|
const msgs = []; let isUserMsg = true;
|
|
545
543
|
chatDivs.forEach((div) => {
|
|
546
544
|
const sender = isUserMsg ? 'USER' : 'CHATGPT'; isUserMsg = !isUserMsg;
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
545
|
+
const msg = Array.from(div.childNodes).map(node => node.innerText)
|
|
546
|
+
.join('\n\n') // insert double line breaks between paragraphs
|
|
547
|
+
.replace('Copy code', '');
|
|
550
548
|
msgs.push(sender + ': ' + msg);
|
|
551
549
|
});
|
|
552
550
|
transcript = msgs.join('\n\n');
|
|
@@ -567,7 +565,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
567
565
|
// Format filename after <title>
|
|
568
566
|
const parser = new DOMParser(),
|
|
569
567
|
parsedHtml = parser.parseFromString(htmlContent, 'text/html');
|
|
570
|
-
filename = parsedHtml.querySelector('title').textContent
|
|
568
|
+
filename = `${ parsedHtml.querySelector('title').textContent || 'ChatGPT conversation' }.html`;
|
|
571
569
|
|
|
572
570
|
// Convert relative CSS paths to absolute ones
|
|
573
571
|
const cssLinks = parsedHtml.querySelectorAll('link[rel="stylesheet"]');
|
|
@@ -864,15 +862,15 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
864
862
|
return formBtnSVG.parentNode.parentNode;
|
|
865
863
|
}},
|
|
866
864
|
|
|
867
|
-
getFooterDiv() { return document.querySelector('main form')
|
|
865
|
+
getFooterDiv() { return document.querySelector('main form')?.parentNode.parentNode.nextElementSibling; },
|
|
868
866
|
getHeaderDiv() { return document.querySelector('main .sticky'); },
|
|
869
867
|
getLastPrompt() { return chatgpt.getChatData('active', 'msg', 'user', 'latest'); },
|
|
870
868
|
getLastResponse() { return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'); },
|
|
871
869
|
|
|
872
870
|
getNewChatButton() {
|
|
873
871
|
for (const navBtnSVG of document.querySelectorAll('nav button svg'))
|
|
874
|
-
if (navBtnSVG.querySelector('path[d
|
|
875
|
-
+ 'path[d
|
|
872
|
+
if (navBtnSVG.querySelector('path[d^="M15.6729"], ' // pencil-on-pad icon
|
|
873
|
+
+ 'path[d^="M3.06957"]')) // refresh icon if temp chat
|
|
876
874
|
return navBtnSVG.parentNode;
|
|
877
875
|
},
|
|
878
876
|
|
|
@@ -1134,7 +1132,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1134
1132
|
const optionButtons = document.querySelectorAll('a[role="menuitem"]');
|
|
1135
1133
|
let cssClasses;
|
|
1136
1134
|
|
|
1137
|
-
for (
|
|
1135
|
+
for (const navLink of optionButtons)
|
|
1138
1136
|
if (navLink.textContent == 'Settings') {
|
|
1139
1137
|
cssClasses = navLink.classList;
|
|
1140
1138
|
break; }
|
|
@@ -1152,7 +1150,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1152
1150
|
this.elements.push(newElement);
|
|
1153
1151
|
const menuBtn = document.querySelector('nav button[id*="headless"]');
|
|
1154
1152
|
if (!this.addedEvent) { // to prevent adding more than one event
|
|
1155
|
-
menuBtn
|
|
1153
|
+
menuBtn?.addEventListener('click', () => { setTimeout(addElementsToMenu, 25); });
|
|
1156
1154
|
this.addedEvent = true; }
|
|
1157
1155
|
|
|
1158
1156
|
return newElement.id; // Return the element id
|
|
@@ -1171,7 +1169,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1171
1169
|
|
|
1172
1170
|
minify() { chatgpt.code.minify(); },
|
|
1173
1171
|
|
|
1174
|
-
notify
|
|
1172
|
+
notify(msg, position, notifDuration, shadow) {
|
|
1175
1173
|
notifDuration = notifDuration ? +notifDuration : 1.75; // sec duration to maintain notification visibility
|
|
1176
1174
|
const fadeDuration = 0.35, // sec duration of fade-out
|
|
1177
1175
|
vpYoffset = 23, vpXoffset = 27; // px offset from viewport border
|
|
@@ -1185,7 +1183,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1185
1183
|
|
|
1186
1184
|
// Create/append close button
|
|
1187
1185
|
const closeBtn = document.createElement('div');
|
|
1188
|
-
closeBtn.title = 'Dismiss'; closeBtn.classList.add('notif-close-btn');
|
|
1186
|
+
closeBtn.title = 'Dismiss'; closeBtn.classList.add('notif-close-btn', 'no-mobile-tap-outline');
|
|
1189
1187
|
const closeSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
1190
1188
|
closeSVG.setAttribute('height', '8px');
|
|
1191
1189
|
closeSVG.setAttribute('viewBox', '0 0 14 14');
|
|
@@ -1215,6 +1213,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1215
1213
|
}
|
|
1216
1214
|
notifStyle.innerText = ( // update prev/new style contents
|
|
1217
1215
|
'.chatgpt-notif {'
|
|
1216
|
+
+ '.no-mobile-tap-outline { outline: none ; -webkit-tap-highlight-color: transparent }'
|
|
1218
1217
|
+ 'background-color: black ; padding: 10px 13px 10px 18px ; border-radius: 11px ; border: 1px solid #f5f5f7 ;' // bubble style
|
|
1219
1218
|
+ 'opacity: 0 ; position: fixed ; z-index: 9999 ; font-size: 1.8rem ; color: white ;' // visibility
|
|
1220
1219
|
+ '-webkit-user-select: none ; -moz-user-select: none ; -ms-user-select: none ; user-select: none ;'
|
|
@@ -1270,15 +1269,17 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1270
1269
|
clearTimeout(dismissFuncTID);
|
|
1271
1270
|
};
|
|
1272
1271
|
const dismissFuncTID = setTimeout(dismissNotif, hideDelay * 1000); // maintain visibility for `hideDelay` secs, then dismiss
|
|
1273
|
-
closeSVG.
|
|
1272
|
+
closeSVG.onclick = dismissNotif; // add to close button clicks
|
|
1274
1273
|
|
|
1275
1274
|
// Destroy notification
|
|
1276
|
-
notificationDiv.
|
|
1275
|
+
notificationDiv.onanimationend = () => {
|
|
1277
1276
|
notificationDiv.remove(); // remove from DOM
|
|
1278
1277
|
notifyProps = JSON.parse(localStorage.notifyProps);
|
|
1279
1278
|
notifyProps.queue[notificationDiv.quadrant].shift(); // + memory
|
|
1280
1279
|
localStorage.notifyProps = JSON.stringify(notifyProps); // + storage
|
|
1281
|
-
}
|
|
1280
|
+
};
|
|
1281
|
+
|
|
1282
|
+
return notificationDiv;
|
|
1282
1283
|
},
|
|
1283
1284
|
|
|
1284
1285
|
obfuscate() { chatgpt.code.obfuscate(); },
|
|
@@ -1409,7 +1410,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1409
1410
|
return node; // if assignment used
|
|
1410
1411
|
},
|
|
1411
1412
|
|
|
1412
|
-
|
|
1413
|
+
async resend() { chatgpt.send(await chatgpt.getChatData('latest', 'msg', 'user', 'latest')); },
|
|
1413
1414
|
|
|
1414
1415
|
response: {
|
|
1415
1416
|
continue() { try { chatgpt.getContinueBtn().click(); } catch (err) { console.error(err.message); }},
|
|
@@ -1437,36 +1438,35 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1437
1438
|
const responseDivs = document.querySelectorAll('div[data-testid*="conversation-turn"]:nth-child(odd)'),
|
|
1438
1439
|
strPos = pos.toString().toLowerCase();
|
|
1439
1440
|
let response = '';
|
|
1440
|
-
if (responseDivs.length)
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
}
|
|
1468
|
-
response = response.replace(/^ChatGPT(?:ChatGPT)?/, ''); // strip sender name
|
|
1441
|
+
if (!responseDivs.length) return console.error('No conversation found!');
|
|
1442
|
+
if (/last|final/.test(strPos)) // get last response
|
|
1443
|
+
response = responseDivs[responseDivs.length - 1].textContent;
|
|
1444
|
+
else { // get nth response
|
|
1445
|
+
const nthOfResponse = (
|
|
1446
|
+
|
|
1447
|
+
// Calculate base number
|
|
1448
|
+
Number.isInteger(pos) ? pos : // do nothing for integers
|
|
1449
|
+
/^\d+/.test(strPos) ? /^\d+/.exec(strPos)[0] : // extract first digits for strings w/ them
|
|
1450
|
+
( // convert words to integers for digitless strings
|
|
1451
|
+
/^(?:1|one|fir)(?:st)?$/.test(strPos) ? 1
|
|
1452
|
+
: /^(?:2|tw(?:o|en|el(?:ve|f))|seco)(?:nd|t[yi])?(?:e?th)?$/.test(strPos) ? 2
|
|
1453
|
+
: /^(?:3|th(?:ree|ir?))(?:rd|teen|t[yi])?(?:e?th)?$/.test(strPos) ? 3
|
|
1454
|
+
: /^(?:4|fou?r)(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 4
|
|
1455
|
+
: /^(?:5|fi(?:ve|f))(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 5
|
|
1456
|
+
: /^(?:6|six)(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 6
|
|
1457
|
+
: /^(?:7|seven)(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 7
|
|
1458
|
+
: /^(?:8|eight?)(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 8
|
|
1459
|
+
: /^(?:9|nine?)(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 9
|
|
1460
|
+
: /^(?:10|ten)(?:th)?$/.test(strPos) ? 10 : 1 )
|
|
1461
|
+
|
|
1462
|
+
// Transform base number if suffixed
|
|
1463
|
+
* ( /(ty|ieth)$/.test(strPos) ? 10 : 1 ) // x 10 if -ty/ieth
|
|
1464
|
+
+ ( /teen(th)?$/.test(strPos) ? 10 : 0 ) // + 10 if -teen/teenth
|
|
1465
|
+
|
|
1466
|
+
);
|
|
1467
|
+
response = responseDivs[nthOfResponse - 1].textContent;
|
|
1469
1468
|
}
|
|
1469
|
+
response = response.replace(/^ChatGPT(?:ChatGPT)?/, ''); // strip sender name
|
|
1470
1470
|
return response;
|
|
1471
1471
|
},
|
|
1472
1472
|
|
|
@@ -1481,17 +1481,17 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1481
1481
|
send(msg, method='') {
|
|
1482
1482
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
1483
1483
|
return console.error(`Argument ${ i + 1 } must be a string!`);
|
|
1484
|
-
const textArea =
|
|
1485
|
-
|
|
1484
|
+
const textArea = chatgpt.getChatBox();
|
|
1485
|
+
if (!textArea) return console.error('Chatbar element not found!');
|
|
1486
1486
|
textArea.value = msg;
|
|
1487
1487
|
textArea.dispatchEvent(new Event('input', { bubbles: true })); // enable send button
|
|
1488
|
-
|
|
1489
1488
|
setTimeout(function delaySend() {
|
|
1489
|
+
const sendBtn = chatgpt.getSendButton();
|
|
1490
1490
|
if (!sendBtn?.hasAttribute('disabled')) { // send msg
|
|
1491
1491
|
method.toLowerCase() == 'click' || chatgpt.browser.isMobile() ? sendBtn.click()
|
|
1492
|
-
: textArea.dispatchEvent(new KeyboardEvent('keydown', {
|
|
1493
|
-
} else setTimeout(delaySend,
|
|
1494
|
-
},
|
|
1492
|
+
: textArea.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
|
|
1493
|
+
} else setTimeout(delaySend, 222);
|
|
1494
|
+
}, 222);
|
|
1495
1495
|
},
|
|
1496
1496
|
|
|
1497
1497
|
sendInNewChat(msg) {
|
|
@@ -1531,7 +1531,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1531
1531
|
}
|
|
1532
1532
|
},
|
|
1533
1533
|
|
|
1534
|
-
|
|
1534
|
+
async sentiment(text, entity) {
|
|
1535
1535
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
1536
1536
|
return console.error(`Argument ${ i + 1 } must be a string.`);
|
|
1537
1537
|
chatgpt.send('What is the sentiment of the following text'
|
|
@@ -1654,8 +1654,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1654
1654
|
element.style.margin = '2px 0';
|
|
1655
1655
|
});
|
|
1656
1656
|
|
|
1657
|
-
const navBar = document.querySelector('nav');
|
|
1658
1657
|
// Create MutationObserver instance
|
|
1658
|
+
const navBar = document.querySelector('nav');
|
|
1659
|
+
if (!navBar) return console.error('Sidebar element not found!');
|
|
1659
1660
|
this.observer = new MutationObserver(mutations => {
|
|
1660
1661
|
mutations.forEach(mutation => {
|
|
1661
1662
|
if ((mutation.type == 'childList' && mutation.addedNodes.length) ||
|
|
@@ -1741,6 +1742,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1741
1742
|
isOff() { return !this.isOn(); },
|
|
1742
1743
|
isOn() {
|
|
1743
1744
|
const sidebar = document.querySelector('body script + div > div');
|
|
1745
|
+
if (!sidebar) return console.error('Sidebar element not found!');
|
|
1744
1746
|
return chatgpt.browser.isMobile() ?
|
|
1745
1747
|
document.documentElement.style.overflow == 'hidden'
|
|
1746
1748
|
: sidebar.style.visibility != 'hidden' && sidebar.style.width != '0px';
|
|
@@ -1750,12 +1752,12 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1750
1752
|
const isMobileDevice = chatgpt.browser.isMobile(),
|
|
1751
1753
|
navBtnSelector = isMobileDevice ? 'button' : 'nav button',
|
|
1752
1754
|
isToggleBtn = isMobileDevice ? () => true // since 1st one is toggle
|
|
1753
|
-
: btn => btn.querySelector('svg path[d
|
|
1755
|
+
: btn => btn.querySelector('svg path[d^="M8.857"]');
|
|
1754
1756
|
for (const btn of document.querySelectorAll(navBtnSelector))
|
|
1755
1757
|
if (isToggleBtn(btn)) { btn.click(); return; }
|
|
1756
1758
|
},
|
|
1757
1759
|
|
|
1758
|
-
|
|
1760
|
+
async isLoaded() {
|
|
1759
1761
|
await chatgpt.isLoaded();
|
|
1760
1762
|
return Promise.race([
|
|
1761
1763
|
new Promise(resolve => {
|
|
@@ -1771,7 +1773,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1771
1773
|
startNewChat() { try { chatgpt.getNewChatBtn().click(); } catch (err) { console.error(err.message); }},
|
|
1772
1774
|
stop() { chatgpt.response.stopGenerating(); },
|
|
1773
1775
|
|
|
1774
|
-
|
|
1776
|
+
async suggest(ideaType, details) {
|
|
1775
1777
|
if (!ideaType) return console.error('ideaType (1st argument) not supplied'
|
|
1776
1778
|
+ '(e.g. \'gifts\', \'names\', \'recipes\', etc.)');
|
|
1777
1779
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
@@ -1809,7 +1811,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1809
1811
|
} catch (err) { console.error( err); }
|
|
1810
1812
|
},
|
|
1811
1813
|
|
|
1812
|
-
|
|
1814
|
+
async summarize(text) {
|
|
1813
1815
|
if (!text) return console.error('Text (1st) argument not supplied. Pass some text!');
|
|
1814
1816
|
if (typeof text !== 'string') return console.error('Text argument must be a string!');
|
|
1815
1817
|
chatgpt.send('Summarize the following text:\n\n' + text);
|
|
@@ -1820,7 +1822,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1820
1822
|
|
|
1821
1823
|
toggleScheme() { chatgpt.settings.scheme.toggle(); },
|
|
1822
1824
|
|
|
1823
|
-
|
|
1825
|
+
async translate(text, outputLang) {
|
|
1824
1826
|
if (!text) return console.error('Text (1st) argument not supplied. Pass some text!');
|
|
1825
1827
|
if (!outputLang) return console.error('outputLang (2nd) argument not supplied. Pass a language!');
|
|
1826
1828
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
// @description A Greasemonkey template to start using chatgpt.js like a boss
|
|
4
4
|
// @author chatgpt.js
|
|
5
5
|
// @namespace https://chatgpt.js.org
|
|
6
|
-
// @version 2024.8.
|
|
6
|
+
// @version 2024.8.29
|
|
7
7
|
// @license MIT
|
|
8
8
|
// @match *://chatgpt.com/*
|
|
9
9
|
// @match *://chat.openai.com/*
|
|
10
|
-
// @icon https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@3.0
|
|
11
|
-
// @icon64 https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@3.0
|
|
12
|
-
// @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.0
|
|
10
|
+
// @icon https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@3.1.0/starters/greasemonkey/media/images/icons/robot/icon48.png
|
|
11
|
+
// @icon64 https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@3.1.0/starters/greasemonkey/media/images/icons/robot/icon64.png
|
|
12
|
+
// @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.1.0/dist/chatgpt.min.js
|
|
13
13
|
// @grant GM_getValue
|
|
14
14
|
// @grant GM_setValue
|
|
15
15
|
// @noframes
|