@kudoai/chatgpt.js 3.0.1 → 3.0.3
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 +12 -10
- package/chatgpt.js +131 -132
- package/dist/chatgpt.min.js +1 -1
- package/docs/README.md +12 -10
- package/docs/USERGUIDE.md +3 -3
- package/package.json +5 -5
- package/starters/chrome/extension/lib/chatgpt.js +131 -132
- package/starters/chrome/extension/manifest.json +1 -1
- package/starters/greasemonkey/chatgpt.js-greasemonkey-starter.user.js +4 -4
|
@@ -20,7 +20,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
20
20
|
instructions: 'https://chatgpt.com/backend-api/user_system_messages'
|
|
21
21
|
}},
|
|
22
22
|
|
|
23
|
-
actAs
|
|
23
|
+
actAs(persona) {
|
|
24
24
|
// Prompts ChatGPT to act as a persona from https://github.com/KudoAI/chat-prompts/blob/main/personas.json
|
|
25
25
|
|
|
26
26
|
const promptsUrl = 'https://raw.githubusercontent.com/KudoAI/chat-prompts/main/dist/personas.min.json';
|
|
@@ -48,19 +48,19 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
48
48
|
});
|
|
49
49
|
},
|
|
50
50
|
|
|
51
|
-
activateDarkMode
|
|
51
|
+
activateDarkMode() {
|
|
52
52
|
document.documentElement.classList.replace('light', 'dark');
|
|
53
53
|
document.documentElement.style.colorScheme = 'dark';
|
|
54
54
|
localStorage.setItem('theme', 'dark');
|
|
55
55
|
},
|
|
56
56
|
|
|
57
|
-
activateLightMode
|
|
57
|
+
activateLightMode() {
|
|
58
58
|
document.documentElement.classList.replace('dark', 'light');
|
|
59
59
|
document.documentElement.style.colorScheme = 'light';
|
|
60
60
|
localStorage.setItem('theme', 'light');
|
|
61
61
|
},
|
|
62
62
|
|
|
63
|
-
alert
|
|
63
|
+
alert(title, msg, btns, checkbox, width) {
|
|
64
64
|
// [ title/msg = strings, btns = [named functions], checkbox = named function, width (px) = int ] = optional
|
|
65
65
|
// * Spaces are inserted into button labels by parsing function names in camel/kebab/snake case
|
|
66
66
|
|
|
@@ -282,13 +282,13 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
282
282
|
return modalContainer.id; // if assignment used
|
|
283
283
|
},
|
|
284
284
|
|
|
285
|
-
|
|
285
|
+
async askAndGetReply(query) {
|
|
286
286
|
chatgpt.send(query); await chatgpt.isIdle();
|
|
287
287
|
return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest');
|
|
288
288
|
},
|
|
289
289
|
|
|
290
290
|
autoRefresh: {
|
|
291
|
-
activate
|
|
291
|
+
activate(interval) {
|
|
292
292
|
if (this.isActive) { // already running, do nothing
|
|
293
293
|
console.log('↻ ChatGPT >> [' + chatgpt.autoRefresh.nowTimeStamp() + '] Auto refresh already active!'); return; }
|
|
294
294
|
|
|
@@ -313,7 +313,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
313
313
|
document.addEventListener('visibilitychange', this.toggle.beacons); }
|
|
314
314
|
},
|
|
315
315
|
|
|
316
|
-
deactivate
|
|
316
|
+
deactivate() {
|
|
317
317
|
if (this.isActive) {
|
|
318
318
|
this.toggle.refreshFrame();
|
|
319
319
|
document.removeEventListener('visibilitychange', this.toggle.beacons);
|
|
@@ -322,7 +322,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
322
322
|
} else { console.log('↻ ChatGPT >> [' + chatgpt.autoRefresh.nowTimeStamp() + '] Auto refresh already inactive!'); }
|
|
323
323
|
},
|
|
324
324
|
|
|
325
|
-
nowTimeStamp
|
|
325
|
+
nowTimeStamp() {
|
|
326
326
|
const now = new Date();
|
|
327
327
|
const hours = now.getHours() % 12 || 12; // Convert to 12-hour format
|
|
328
328
|
let minutes = now.getMinutes(), seconds = now.getSeconds();
|
|
@@ -333,7 +333,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
333
333
|
|
|
334
334
|
toggle: {
|
|
335
335
|
|
|
336
|
-
beacons
|
|
336
|
+
beacons() {
|
|
337
337
|
if (chatgpt.autoRefresh.beaconID) {
|
|
338
338
|
clearInterval(chatgpt.autoRefresh.beaconID); chatgpt.autoRefresh.beaconID = null;
|
|
339
339
|
console.log('↻ ChatGPT >> [' + chatgpt.autoRefresh.nowTimeStamp() + '] Beacons de-activated');
|
|
@@ -346,7 +346,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
346
346
|
}
|
|
347
347
|
},
|
|
348
348
|
|
|
349
|
-
refreshFrame
|
|
349
|
+
refreshFrame() {
|
|
350
350
|
let refreshFrame = document.querySelector('#refresh-frame');
|
|
351
351
|
if (refreshFrame) refreshFrame.remove();
|
|
352
352
|
else {
|
|
@@ -360,26 +360,26 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
360
360
|
|
|
361
361
|
browser: {
|
|
362
362
|
|
|
363
|
-
isLightMode
|
|
364
|
-
isDarkMode
|
|
365
|
-
isChromium
|
|
366
|
-
isChrome
|
|
367
|
-
isEdge
|
|
368
|
-
isBrave
|
|
369
|
-
isFirefox
|
|
363
|
+
isLightMode() { return window.matchMedia?.('(prefers-color-scheme: light)')?.matches; },
|
|
364
|
+
isDarkMode() { return window.matchMedia?.('(prefers-color-scheme: dark)')?.matches; },
|
|
365
|
+
isChromium() { return !!JSON.stringify(navigator.userAgentData?.brands)?.includes('Chromium'); },
|
|
366
|
+
isChrome() { return !!JSON.stringify(navigator.userAgentData?.brands)?.includes('Chrome'); },
|
|
367
|
+
isEdge() { return !!JSON.stringify(navigator.userAgentData?.brands)?.includes('Edge'); },
|
|
368
|
+
isBrave() { return !!JSON.stringify(navigator.userAgentData?.brands)?.includes('Brave'); },
|
|
369
|
+
isFirefox() { return navigator.userAgent.includes('Firefox'); },
|
|
370
370
|
|
|
371
|
-
isFullScreen
|
|
371
|
+
isFullScreen() {
|
|
372
372
|
const userAgentStr = navigator.userAgent;
|
|
373
373
|
return userAgentStr.includes('Chrome') ? window.matchMedia('(display-mode: fullscreen)').matches
|
|
374
374
|
: userAgentStr.includes('Firefox') ? window.fullScreen
|
|
375
375
|
: /MSIE|rv:/.test(userAgentStr) ? document.msFullscreenElement : document.webkitIsFullScreen;
|
|
376
376
|
},
|
|
377
377
|
|
|
378
|
-
isMobile
|
|
378
|
+
isMobile() {
|
|
379
379
|
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); }
|
|
380
380
|
},
|
|
381
381
|
|
|
382
|
-
|
|
382
|
+
async clearChats() { // back-end method
|
|
383
383
|
return new Promise((resolve, reject) => {
|
|
384
384
|
chatgpt.getAccessToken().then(token => {
|
|
385
385
|
const xhr = new XMLHttpRequest();
|
|
@@ -398,7 +398,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
398
398
|
code: {
|
|
399
399
|
// Tip: Use template literals for easier passing of code arguments. Ensure backticks and `$`s are escaped (using `\`)
|
|
400
400
|
|
|
401
|
-
|
|
401
|
+
async execute(code) {
|
|
402
402
|
if (!code) return console.error('Code argument not supplied. Pass some code!');
|
|
403
403
|
if (typeof code !== 'string') return console.error('Code argument must be a string!');
|
|
404
404
|
chatgpt.send('Display the output as if you were terminal:\n\n' + code);
|
|
@@ -407,12 +407,12 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
407
407
|
return chatgpt.code.extract(await chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'));
|
|
408
408
|
},
|
|
409
409
|
|
|
410
|
-
extract
|
|
410
|
+
extract(msg) { // extract pure code from response (targets last block)
|
|
411
411
|
const codeBlocks = msg.match(/(?<=```.*\n)[\s\S]*?(?=```)/g);
|
|
412
412
|
return codeBlocks ? codeBlocks[codeBlocks.length - 1] : msg;
|
|
413
413
|
},
|
|
414
414
|
|
|
415
|
-
|
|
415
|
+
async isIdle() {
|
|
416
416
|
await new Promise(resolve => { // when in conversation page
|
|
417
417
|
(function checkConvoPage() {
|
|
418
418
|
document.querySelector('div[data-message-author-role]') ? resolve(true)
|
|
@@ -440,7 +440,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
440
440
|
]);
|
|
441
441
|
},
|
|
442
442
|
|
|
443
|
-
|
|
443
|
+
async minify(code) {
|
|
444
444
|
if (!code) return console.error('Code argument not supplied. Pass some code!');
|
|
445
445
|
if (typeof code !== 'string') return console.error('Code argument must be a string!');
|
|
446
446
|
chatgpt.send('Minify the following code:\n\n' + code);
|
|
@@ -449,7 +449,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
449
449
|
return chatgpt.code.extract(await chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'));
|
|
450
450
|
},
|
|
451
451
|
|
|
452
|
-
|
|
452
|
+
async obfuscate(code) {
|
|
453
453
|
if (!code) return console.error('Code argument not supplied. Pass some code!');
|
|
454
454
|
if (typeof code !== 'string') return console.error('Code argument must be a string!');
|
|
455
455
|
chatgpt.send('Obfuscate the following code:\n\n' + code);
|
|
@@ -458,7 +458,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
458
458
|
return chatgpt.code.extract(await chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'));
|
|
459
459
|
},
|
|
460
460
|
|
|
461
|
-
|
|
461
|
+
async refactor(code, objective) {
|
|
462
462
|
if (!code) return console.error('Code (1st) argument not supplied. Pass some code!');
|
|
463
463
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
464
464
|
return console.error(`Argument ${ i + 1 } must be a string.`);
|
|
@@ -468,7 +468,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
468
468
|
return chatgpt.code.extract(await chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'));
|
|
469
469
|
},
|
|
470
470
|
|
|
471
|
-
|
|
471
|
+
async review(code) {
|
|
472
472
|
if (!code) return console.error('Code argument not supplied. Pass some code!');
|
|
473
473
|
if (typeof code !== 'string') return console.error('Code argument must be a string!');
|
|
474
474
|
chatgpt.send('Review the following code for me:\n\n' + code);
|
|
@@ -477,7 +477,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
477
477
|
return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest');
|
|
478
478
|
},
|
|
479
479
|
|
|
480
|
-
|
|
480
|
+
async unminify(code) {
|
|
481
481
|
if (!code) return console.error('Code argument not supplied. Pass some code!');
|
|
482
482
|
if (typeof code !== 'string') return console.error('Code argument must be a string!');
|
|
483
483
|
chatgpt.send('Unminify the following code.:\n\n' + code);
|
|
@@ -486,7 +486,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
486
486
|
return chatgpt.code.extract(await chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'));
|
|
487
487
|
},
|
|
488
488
|
|
|
489
|
-
|
|
489
|
+
async write(prompt, outputLang) {
|
|
490
490
|
if (!prompt) return console.error('Prompt (1st) argument not supplied. Pass a prompt!');
|
|
491
491
|
if (!outputLang) return console.error('outputLang (2nd) argument not supplied. Pass a language!');
|
|
492
492
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
@@ -498,9 +498,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
498
498
|
}
|
|
499
499
|
},
|
|
500
500
|
|
|
501
|
-
continue
|
|
501
|
+
continue() { chatgpt.response.continue(); },
|
|
502
502
|
|
|
503
|
-
|
|
503
|
+
async detectLanguage(text) {
|
|
504
504
|
if (!text) return console.error('Text argument not supplied. Pass some text!');
|
|
505
505
|
if (typeof text !== 'string') return console.error('Text argument must be a string!');
|
|
506
506
|
chatgpt.send('Detect the language of the following text:\n\n' + text
|
|
@@ -510,9 +510,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
510
510
|
return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest');
|
|
511
511
|
},
|
|
512
512
|
|
|
513
|
-
executeCode
|
|
513
|
+
executeCode() { chatgpt.code.execute(); },
|
|
514
514
|
|
|
515
|
-
|
|
515
|
+
async exportChat(chatToGet, format) {
|
|
516
516
|
// chatToGet = 'active' (default) | 'latest' | index|title|id of chat to get
|
|
517
517
|
// format = 'html' (default) | 'md' | 'pdf' | 'text'
|
|
518
518
|
|
|
@@ -609,16 +609,16 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
609
609
|
}
|
|
610
610
|
},
|
|
611
611
|
|
|
612
|
-
extractCode
|
|
613
|
-
focusChatbar
|
|
612
|
+
extractCode() { chatgpt.code.extract(); },
|
|
613
|
+
focusChatbar() { chatgpt.getChatBox()?.focus(); },
|
|
614
614
|
|
|
615
|
-
generateRandomIP
|
|
615
|
+
generateRandomIP() {
|
|
616
616
|
const ip = Array.from({length: 4}, () => Math.floor(chatgpt.randomFloat() * 256)).join('.');
|
|
617
617
|
console.info('IP generated: ' + ip);
|
|
618
618
|
return ip;
|
|
619
619
|
},
|
|
620
620
|
|
|
621
|
-
get
|
|
621
|
+
get(targetType, targetName = '') {
|
|
622
622
|
// targetType = 'button'|'link'|'div'|'response'
|
|
623
623
|
// targetName = from get[targetName][targetType] methods, e.g. 'send'
|
|
624
624
|
|
|
@@ -651,7 +651,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
651
651
|
return this[targetFuncName](); // call found function
|
|
652
652
|
},
|
|
653
653
|
|
|
654
|
-
getAccessToken
|
|
654
|
+
getAccessToken() {
|
|
655
655
|
return new Promise((resolve, reject) => {
|
|
656
656
|
if (Object.keys(chatgpt.openAIaccessToken).length > 0 && // populated
|
|
657
657
|
(Date.parse(chatgpt.openAIaccessToken.expireDate) - Date.parse(new Date()) >= 0)) // not expired
|
|
@@ -672,7 +672,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
672
672
|
});
|
|
673
673
|
},
|
|
674
674
|
|
|
675
|
-
getAccountDetails
|
|
675
|
+
getAccountDetails(...details) {
|
|
676
676
|
// details = [email|id|image|name|picture] = optional
|
|
677
677
|
|
|
678
678
|
// Build details array
|
|
@@ -703,9 +703,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
703
703
|
});
|
|
704
704
|
},
|
|
705
705
|
|
|
706
|
-
getChatBox
|
|
706
|
+
getChatBox() { return document.getElementById('prompt-textarea'); },
|
|
707
707
|
|
|
708
|
-
getChatData
|
|
708
|
+
getChatData(chatToGet = 1, detailsToGet = 'all', sender = 'all', msgToGet = 'all') {
|
|
709
709
|
// chatToGet = 'active' | 'latest' | index|title|id of chat to get (defaults to active OpenAI chat > latest chat)
|
|
710
710
|
// detailsToGet = 'all' | [ 'id' | 'title' | 'create_time' | 'update_time' | 'msg' ] (defaults to 'all', excludes msg's)
|
|
711
711
|
// sender = ( 'all' | 'both' ) | 'user' | 'chatgpt' (defaults to 'all', requires 2nd param = 'msg')
|
|
@@ -856,35 +856,35 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
856
856
|
}));
|
|
857
857
|
},
|
|
858
858
|
|
|
859
|
-
getChatInput
|
|
859
|
+
getChatInput() { return chatgpt.getChatBox().value; },
|
|
860
860
|
|
|
861
|
-
getContinueGeneratingButton
|
|
861
|
+
getContinueGeneratingButton() {
|
|
862
862
|
for (const formBtnSVG of document.querySelectorAll('form button svg')) {
|
|
863
863
|
if (formBtnSVG.querySelector('path[d*="M4.472 2.5a1"]'))
|
|
864
864
|
return formBtnSVG.parentNode.parentNode;
|
|
865
865
|
}},
|
|
866
866
|
|
|
867
|
-
getFooterDiv
|
|
868
|
-
getHeaderDiv
|
|
869
|
-
getLastPrompt
|
|
870
|
-
getLastResponse
|
|
867
|
+
getFooterDiv() { return document.querySelector('main form').parentNode.parentNode.nextElementSibling; },
|
|
868
|
+
getHeaderDiv() { return document.querySelector('main .sticky'); },
|
|
869
|
+
getLastPrompt() { return chatgpt.getChatData('active', 'msg', 'user', 'latest'); },
|
|
870
|
+
getLastResponse() { return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'); },
|
|
871
871
|
|
|
872
|
-
getNewChatButton
|
|
872
|
+
getNewChatButton() {
|
|
873
873
|
for (const navBtnSVG of document.querySelectorAll('nav button svg'))
|
|
874
874
|
if (navBtnSVG.querySelector('path[d*="M15.673 3.913a3.121"], ' // pencil-on-pad icon
|
|
875
875
|
+ 'path[d*="M3.07 10.876C3.623"]')) // refresh icon if temp chat
|
|
876
876
|
return navBtnSVG.parentNode;
|
|
877
877
|
},
|
|
878
878
|
|
|
879
|
-
getNewChatLink
|
|
879
|
+
getNewChatLink() { return document.querySelector('nav a[href="/"]'); },
|
|
880
880
|
|
|
881
|
-
getRegenerateButton
|
|
881
|
+
getRegenerateButton() {
|
|
882
882
|
for (const mainSVG of document.querySelectorAll('main svg')) {
|
|
883
883
|
if (mainSVG.querySelector('path[d*="M3.07 10.876C3.623"]')) // regen icon found
|
|
884
884
|
return mainSVG.parentNode;
|
|
885
885
|
}},
|
|
886
886
|
|
|
887
|
-
getResponse
|
|
887
|
+
getResponse() {
|
|
888
888
|
// * Returns response via DOM by index arg if OpenAI chat page is active, otherwise uses API w/ following args:
|
|
889
889
|
// chatToGet = index|title|id of chat to get (defaults to latest if '' unpassed)
|
|
890
890
|
// responseToGet = index of response to get (defaults to latest if '' unpassed)
|
|
@@ -893,30 +893,30 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
893
893
|
return chatgpt.response.get(...arguments);
|
|
894
894
|
},
|
|
895
895
|
|
|
896
|
-
getResponseFromAPI
|
|
897
|
-
getResponseFromDOM
|
|
898
|
-
getScrollToBottomButton
|
|
896
|
+
getResponseFromAPI(chatToGet, responseToGet) { return chatgpt.response.getFromAPI(chatToGet, responseToGet); },
|
|
897
|
+
getResponseFromDOM(pos) { return chatgpt.response.getFromDOM(pos); },
|
|
898
|
+
getScrollToBottomButton() { return document.querySelector('button[class*="cursor"][class*="bottom"]'); },
|
|
899
899
|
|
|
900
|
-
getSendButton
|
|
900
|
+
getSendButton() {
|
|
901
901
|
return document.querySelector('[data-testid="send-button"]') // pre-GPT-4o
|
|
902
902
|
|| document.querySelector('path[d*="M15.192 8.906a1.143"]')?.parentNode.parentNode; // post-GPT-4o
|
|
903
903
|
},
|
|
904
904
|
|
|
905
|
-
getStopGeneratingButton
|
|
905
|
+
getStopGeneratingButton() {
|
|
906
906
|
for (const svg of document.querySelectorAll('form button svg')) {
|
|
907
907
|
if (svg.querySelector('path[d*="2 0 0 1 2"], rect'))
|
|
908
908
|
return svg.parentNode;
|
|
909
909
|
}},
|
|
910
910
|
|
|
911
|
-
getUserLanguage
|
|
911
|
+
getUserLanguage() {
|
|
912
912
|
return navigator.languages[0] || navigator.language || navigator.browserLanguage ||
|
|
913
913
|
navigator.systemLanguage || navigator.userLanguage || ''; },
|
|
914
914
|
|
|
915
|
-
hideFooter
|
|
916
|
-
hideHeader
|
|
915
|
+
hideFooter() { chatgpt.getFooterDiv().style.display = 'none'; },
|
|
916
|
+
hideHeader() { chatgpt.getHeaderDiv().style.display = 'none'; },
|
|
917
917
|
|
|
918
918
|
history: {
|
|
919
|
-
isLoaded
|
|
919
|
+
isLoaded() {
|
|
920
920
|
return new Promise(resolve => {
|
|
921
921
|
(function checkChatHistory() {
|
|
922
922
|
document.querySelector('nav') ? resolve(true) : setTimeout(checkChatHistory, 200);
|
|
@@ -927,7 +927,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
927
927
|
instructions: {
|
|
928
928
|
// NOTE: DOM is not updated to reflect new instructions added/removed or toggle state (until session refresh)
|
|
929
929
|
|
|
930
|
-
add
|
|
930
|
+
add(instruction, target) {
|
|
931
931
|
if (!instruction) return console.error('Please provide an instruction');
|
|
932
932
|
if (typeof instruction !== 'string') return console.error('Instruction must be a string');
|
|
933
933
|
const validTargets = ['user', 'chatgpt']; // valid targets
|
|
@@ -953,7 +953,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
953
953
|
});
|
|
954
954
|
},
|
|
955
955
|
|
|
956
|
-
clear
|
|
956
|
+
clear(target) {
|
|
957
957
|
const validTargets = ['user', 'chatgpt']; // valid targets
|
|
958
958
|
if (!target) return console.error('Please provide a valid target!');
|
|
959
959
|
if (typeof target !== 'string') return console.error('Target must be a string');
|
|
@@ -974,7 +974,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
974
974
|
});});
|
|
975
975
|
},
|
|
976
976
|
|
|
977
|
-
fetchData
|
|
977
|
+
fetchData() {
|
|
978
978
|
// INTERNAL METHOD
|
|
979
979
|
return new Promise(resolve => {
|
|
980
980
|
chatgpt.getAccessToken().then(async token => {
|
|
@@ -982,7 +982,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
982
982
|
});});
|
|
983
983
|
},
|
|
984
984
|
|
|
985
|
-
sendRequest
|
|
985
|
+
sendRequest(method, token, body) {
|
|
986
986
|
// INTERNAL METHOD
|
|
987
987
|
// Validate args
|
|
988
988
|
for (let i = 0; i < arguments.length - 1; i++) if (typeof arguments[i] !== 'string')
|
|
@@ -1018,7 +1018,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1018
1018
|
});
|
|
1019
1019
|
},
|
|
1020
1020
|
|
|
1021
|
-
turnOff
|
|
1021
|
+
turnOff() {
|
|
1022
1022
|
return new Promise(resolve => {
|
|
1023
1023
|
chatgpt.getAccessToken().then(async token => {
|
|
1024
1024
|
const instructionsData = await this.fetchData();
|
|
@@ -1029,7 +1029,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1029
1029
|
});
|
|
1030
1030
|
},
|
|
1031
1031
|
|
|
1032
|
-
turnOn
|
|
1032
|
+
turnOn() {
|
|
1033
1033
|
return new Promise(resolve => {
|
|
1034
1034
|
chatgpt.getAccessToken().then(async token => {
|
|
1035
1035
|
const instructionsData = await this.fetchData();
|
|
@@ -1040,7 +1040,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1040
1040
|
});
|
|
1041
1041
|
},
|
|
1042
1042
|
|
|
1043
|
-
toggle
|
|
1043
|
+
toggle() {
|
|
1044
1044
|
return new Promise(resolve => {
|
|
1045
1045
|
this.fetchData().then(async instructionsData => {
|
|
1046
1046
|
await (instructionsData.enabled ? this.turnOff() : this.turnOn());
|
|
@@ -1049,32 +1049,32 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1049
1049
|
}
|
|
1050
1050
|
},
|
|
1051
1051
|
|
|
1052
|
-
isDarkMode
|
|
1053
|
-
isFullScreen
|
|
1052
|
+
isDarkMode() { return document.documentElement.classList.toString().includes('dark'); },
|
|
1053
|
+
isFullScreen() { return chatgpt.browser.isFullScreen(); },
|
|
1054
1054
|
|
|
1055
|
-
isIdle
|
|
1055
|
+
isIdle() {
|
|
1056
1056
|
return new Promise(resolve => {
|
|
1057
1057
|
(function checkIsIdle() {
|
|
1058
1058
|
chatgpt.getRegenerateButton() ? resolve(true) : setTimeout(checkIsIdle, 200);
|
|
1059
1059
|
})();
|
|
1060
1060
|
});},
|
|
1061
1061
|
|
|
1062
|
-
isLoaded
|
|
1062
|
+
isLoaded() {
|
|
1063
1063
|
return new Promise(resolve => {
|
|
1064
1064
|
(function checkIsLoaded() {
|
|
1065
1065
|
chatgpt.getNewChatButton() ? resolve(true) : setTimeout(checkIsLoaded, 200);
|
|
1066
1066
|
})();
|
|
1067
1067
|
});},
|
|
1068
1068
|
|
|
1069
|
-
isLightMode
|
|
1069
|
+
isLightMode() { return document.documentElement.classList.toString().includes('light'); },
|
|
1070
1070
|
|
|
1071
|
-
logout
|
|
1071
|
+
logout() { window.location.href = 'https://chat.openai.com/auth/logout'; },
|
|
1072
1072
|
|
|
1073
1073
|
menu: {
|
|
1074
1074
|
elements: [],
|
|
1075
1075
|
addedEvent: false,
|
|
1076
1076
|
|
|
1077
|
-
append
|
|
1077
|
+
append(element, attrs = {}) {
|
|
1078
1078
|
// element = 'button' | 'dropdown' REQUIRED (no default value)
|
|
1079
1079
|
// attrs = { ... }
|
|
1080
1080
|
// attrs for 'button': 'icon' = src string, 'label' = string, 'onclick' = function
|
|
@@ -1158,20 +1158,20 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1158
1158
|
return newElement.id; // Return the element id
|
|
1159
1159
|
},
|
|
1160
1160
|
|
|
1161
|
-
close
|
|
1161
|
+
close() {
|
|
1162
1162
|
try { document.querySelector('nav [id*="menu-button"][aria-expanded="true"]').click(); }
|
|
1163
1163
|
catch (err) { console.error(err.message); }
|
|
1164
1164
|
},
|
|
1165
1165
|
|
|
1166
|
-
open
|
|
1166
|
+
open() {
|
|
1167
1167
|
try { document.querySelector('nav [id*="menu-button"][aria-expanded="false"]').click(); }
|
|
1168
1168
|
catch (err) { console.error(err.message); }
|
|
1169
1169
|
}
|
|
1170
1170
|
},
|
|
1171
1171
|
|
|
1172
|
-
minify
|
|
1172
|
+
minify() { chatgpt.code.minify(); },
|
|
1173
1173
|
|
|
1174
|
-
|
|
1174
|
+
async notify(msg, position, notifDuration, shadow) {
|
|
1175
1175
|
notifDuration = notifDuration ? +notifDuration : 1.75; // sec duration to maintain notification visibility
|
|
1176
1176
|
const fadeDuration = 0.35, // sec duration of fade-out
|
|
1177
1177
|
vpYoffset = 23, vpXoffset = 27; // px offset from viewport border
|
|
@@ -1281,9 +1281,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1281
1281
|
}, { once: true });
|
|
1282
1282
|
},
|
|
1283
1283
|
|
|
1284
|
-
obfuscate
|
|
1284
|
+
obfuscate() { chatgpt.code.obfuscate(); },
|
|
1285
1285
|
|
|
1286
|
-
printAllFunctions
|
|
1286
|
+
printAllFunctions() {
|
|
1287
1287
|
|
|
1288
1288
|
// Define colors
|
|
1289
1289
|
const colors = { // element: [light, dark]
|
|
@@ -1349,16 +1349,16 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1349
1349
|
}
|
|
1350
1350
|
},
|
|
1351
1351
|
|
|
1352
|
-
randomFloat
|
|
1352
|
+
randomFloat() {
|
|
1353
1353
|
// * Generates a random, cryptographically secure value between 0 (inclusive) & 1 (exclusive)
|
|
1354
1354
|
const crypto = window.crypto || window.msCrypto;
|
|
1355
1355
|
return crypto?.getRandomValues(new Uint32Array(1))[0] / 0xFFFFFFFF || Math.random();
|
|
1356
1356
|
},
|
|
1357
1357
|
|
|
1358
|
-
refactor
|
|
1359
|
-
regenerate
|
|
1358
|
+
refactor() { chatgpt.code.refactor(); },
|
|
1359
|
+
regenerate() { chatgpt.response.regenerate(); },
|
|
1360
1360
|
|
|
1361
|
-
renderHTML
|
|
1361
|
+
renderHTML(node) {
|
|
1362
1362
|
const reTags = /<([a-z\d]+)\b([^>]*)>([\s\S]*?)<\/\1>/g,
|
|
1363
1363
|
reAttributes = /(\S+)=['"]?((?:.(?!['"]?\s+\S+=|[>']))+.)['"]?/g,
|
|
1364
1364
|
nodeContent = node.childNodes;
|
|
@@ -1409,12 +1409,12 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1409
1409
|
return node; // if assignment used
|
|
1410
1410
|
},
|
|
1411
1411
|
|
|
1412
|
-
|
|
1412
|
+
async resend() { chatgpt.send(await chatgpt.getChatData('latest', 'msg', 'user', 'latest')); },
|
|
1413
1413
|
|
|
1414
1414
|
response: {
|
|
1415
|
-
continue
|
|
1415
|
+
continue() { try { chatgpt.getContinueBtn().click(); } catch (err) { console.error(err.message); }},
|
|
1416
1416
|
|
|
1417
|
-
get
|
|
1417
|
+
get() {
|
|
1418
1418
|
// * Returns response via DOM by index arg if OpenAI chat page is active, otherwise uses API w/ following args:
|
|
1419
1419
|
// chatToGet = index|title|id of chat to get (defaults to latest if '' unpassed)
|
|
1420
1420
|
// responseToGet = index of response to get (defaults to latest if '' unpassed)
|
|
@@ -1425,7 +1425,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1425
1425
|
else return this.getFromAPI.apply(null, arguments);
|
|
1426
1426
|
},
|
|
1427
1427
|
|
|
1428
|
-
getFromAPI
|
|
1428
|
+
getFromAPI(chatToGet, responseToGet) {
|
|
1429
1429
|
// chatToGet = index|title|id of chat to get (defaults to latest if '' or unpassed)
|
|
1430
1430
|
// responseToGet = index of response to get (defaults to latest if '' or unpassed)
|
|
1431
1431
|
|
|
@@ -1433,7 +1433,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1433
1433
|
return chatgpt.getChatData(chatToGet, 'msg', 'chatgpt', responseToGet);
|
|
1434
1434
|
},
|
|
1435
1435
|
|
|
1436
|
-
getFromDOM
|
|
1436
|
+
getFromDOM(pos) {
|
|
1437
1437
|
const responseDivs = document.querySelectorAll('div[data-testid*="conversation-turn"]:nth-child(odd)'),
|
|
1438
1438
|
strPos = pos.toString().toLowerCase();
|
|
1439
1439
|
let response = '';
|
|
@@ -1470,31 +1470,30 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1470
1470
|
return response;
|
|
1471
1471
|
},
|
|
1472
1472
|
|
|
1473
|
-
getLast
|
|
1474
|
-
regenerate
|
|
1475
|
-
stopGenerating
|
|
1473
|
+
getLast() { return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'); },
|
|
1474
|
+
regenerate() { try { chatgpt.getRegenerateBtn().click(); } catch (err) { console.error(err.message); }},
|
|
1475
|
+
stopGenerating() { try { chatgpt.getStopBtn().click(); } catch (err) { console.error(err.message); }}
|
|
1476
1476
|
},
|
|
1477
1477
|
|
|
1478
|
-
reviewCode
|
|
1479
|
-
scrollToBottom
|
|
1478
|
+
reviewCode() { chatgpt.code.review(); },
|
|
1479
|
+
scrollToBottom() { try { chatgpt.getScrollBtn().click(); } catch (err) { console.error(err.message); }},
|
|
1480
1480
|
|
|
1481
|
-
send
|
|
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 = document.querySelector('form textarea')
|
|
1485
|
-
sendBtn = chatgpt.getSendButton();
|
|
1484
|
+
const textArea = document.querySelector('form textarea');
|
|
1486
1485
|
textArea.value = msg;
|
|
1487
1486
|
textArea.dispatchEvent(new Event('input', { bubbles: true })); // enable send button
|
|
1488
|
-
|
|
1489
1487
|
setTimeout(function delaySend() {
|
|
1488
|
+
const sendBtn = chatgpt.getSendButton();
|
|
1490
1489
|
if (!sendBtn?.hasAttribute('disabled')) { // send msg
|
|
1491
1490
|
method.toLowerCase() == 'click' || chatgpt.browser.isMobile() ? sendBtn.click()
|
|
1492
|
-
: textArea.dispatchEvent(new KeyboardEvent('keydown', {
|
|
1493
|
-
} else setTimeout(delaySend,
|
|
1494
|
-
},
|
|
1491
|
+
: textArea.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
|
|
1492
|
+
} else setTimeout(delaySend, 222);
|
|
1493
|
+
}, 222);
|
|
1495
1494
|
},
|
|
1496
1495
|
|
|
1497
|
-
sendInNewChat
|
|
1496
|
+
sendInNewChat(msg) {
|
|
1498
1497
|
if (typeof msg !== 'string') return console.error('Message must be a string!');
|
|
1499
1498
|
for (const navLink of document.querySelectorAll('nav a')) {
|
|
1500
1499
|
if (/(new|clear) chat/i.test(navLink.text)) {
|
|
@@ -1504,9 +1503,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1504
1503
|
|
|
1505
1504
|
settings: {
|
|
1506
1505
|
scheme: {
|
|
1507
|
-
isDark
|
|
1508
|
-
isLight
|
|
1509
|
-
set
|
|
1506
|
+
isDark() { return document.documentElement.classList.contains('dark'); },
|
|
1507
|
+
isLight() { return document.documentElement.classList.contains('light'); },
|
|
1508
|
+
set(value) {
|
|
1510
1509
|
|
|
1511
1510
|
// Validate value
|
|
1512
1511
|
const validValues = ['dark', 'light', 'system'];
|
|
@@ -1522,7 +1521,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1522
1521
|
// Toggle scheme if necessary
|
|
1523
1522
|
if (!document.documentElement.classList.contains(schemeToSet)) this.toggle();
|
|
1524
1523
|
},
|
|
1525
|
-
toggle
|
|
1524
|
+
toggle() {
|
|
1526
1525
|
const [schemeToRemove, schemeToAdd] = this.isDark() ? ['dark', 'light'] : ['light', 'dark'];
|
|
1527
1526
|
document.documentElement.classList.replace(schemeToRemove, schemeToAdd);
|
|
1528
1527
|
document.documentElement.style.colorScheme = schemeToAdd;
|
|
@@ -1531,7 +1530,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1531
1530
|
}
|
|
1532
1531
|
},
|
|
1533
1532
|
|
|
1534
|
-
|
|
1533
|
+
async sentiment(text, entity) {
|
|
1535
1534
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
1536
1535
|
return console.error(`Argument ${ i + 1 } must be a string.`);
|
|
1537
1536
|
chatgpt.send('What is the sentiment of the following text'
|
|
@@ -1542,9 +1541,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1542
1541
|
return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest');
|
|
1543
1542
|
},
|
|
1544
1543
|
|
|
1545
|
-
setScheme
|
|
1544
|
+
setScheme(value) { chatgpt.settings.scheme.set(value); },
|
|
1546
1545
|
|
|
1547
|
-
shareChat
|
|
1546
|
+
shareChat(chatToGet, method = 'clipboard') {
|
|
1548
1547
|
// chatToGet = index|title|id of chat to get (defaults to latest if '' or unpassed)
|
|
1549
1548
|
// method = [ 'alert'|'clipboard' ] (defaults to 'clipboard' if '' or unpassed)
|
|
1550
1549
|
|
|
@@ -1623,13 +1622,13 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1623
1622
|
});});});});});
|
|
1624
1623
|
},
|
|
1625
1624
|
|
|
1626
|
-
showFooter
|
|
1627
|
-
showHeader
|
|
1625
|
+
showFooter() { chatgpt.getFooterDiv().style.display = 'revert'; },
|
|
1626
|
+
showHeader() { chatgpt.getHeaderDiv().style.display = 'flex'; },
|
|
1628
1627
|
|
|
1629
1628
|
sidebar: {
|
|
1630
1629
|
elements: [], observer: {},
|
|
1631
1630
|
|
|
1632
|
-
activateObserver
|
|
1631
|
+
activateObserver() {
|
|
1633
1632
|
|
|
1634
1633
|
// Stop the previous observer to preserve resources
|
|
1635
1634
|
if (this.observer instanceof MutationObserver)
|
|
@@ -1675,7 +1674,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1675
1674
|
this.observer.observe(document.documentElement, { childList: true, subtree: true, attributes: true });
|
|
1676
1675
|
},
|
|
1677
1676
|
|
|
1678
|
-
append
|
|
1677
|
+
append(element, attrs = {}) {
|
|
1679
1678
|
// element = 'button' | 'dropdown' REQUIRED (no default value)
|
|
1680
1679
|
// attrs = { ... }
|
|
1681
1680
|
// attrs for 'button': 'icon' = src string, 'label' = string, 'onclick' = function
|
|
@@ -1736,26 +1735,26 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1736
1735
|
return newElement.id; // Return the element id
|
|
1737
1736
|
},
|
|
1738
1737
|
|
|
1739
|
-
hide
|
|
1740
|
-
show
|
|
1741
|
-
isOff
|
|
1742
|
-
isOn
|
|
1743
|
-
const sidebar = document.querySelector('
|
|
1738
|
+
hide() { this.isOn() ? this.toggle() : console.info('Sidebar already hidden!'); },
|
|
1739
|
+
show() { this.isOff() ? this.toggle() : console.info('Sidebar already shown!'); },
|
|
1740
|
+
isOff() { return !this.isOn(); },
|
|
1741
|
+
isOn() {
|
|
1742
|
+
const sidebar = document.querySelector('body script + div > div');
|
|
1744
1743
|
return chatgpt.browser.isMobile() ?
|
|
1745
1744
|
document.documentElement.style.overflow == 'hidden'
|
|
1746
1745
|
: sidebar.style.visibility != 'hidden' && sidebar.style.width != '0px';
|
|
1747
1746
|
},
|
|
1748
1747
|
|
|
1749
|
-
toggle
|
|
1748
|
+
toggle() {
|
|
1750
1749
|
const isMobileDevice = chatgpt.browser.isMobile(),
|
|
1751
|
-
navBtnSelector = isMobileDevice ? '
|
|
1750
|
+
navBtnSelector = isMobileDevice ? 'button' : 'nav button',
|
|
1752
1751
|
isToggleBtn = isMobileDevice ? () => true // since 1st one is toggle
|
|
1753
|
-
: btn => btn.
|
|
1752
|
+
: btn => btn.querySelector('svg path[d*="M8.857 3h6.286c1.084"]');
|
|
1754
1753
|
for (const btn of document.querySelectorAll(navBtnSelector))
|
|
1755
1754
|
if (isToggleBtn(btn)) { btn.click(); return; }
|
|
1756
1755
|
},
|
|
1757
1756
|
|
|
1758
|
-
|
|
1757
|
+
async isLoaded() {
|
|
1759
1758
|
await chatgpt.isLoaded();
|
|
1760
1759
|
return Promise.race([
|
|
1761
1760
|
new Promise(resolve => {
|
|
@@ -1768,10 +1767,10 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1768
1767
|
}
|
|
1769
1768
|
},
|
|
1770
1769
|
|
|
1771
|
-
startNewChat
|
|
1772
|
-
stop
|
|
1770
|
+
startNewChat() { try { chatgpt.getNewChatBtn().click(); } catch (err) { console.error(err.message); }},
|
|
1771
|
+
stop() { chatgpt.response.stopGenerating(); },
|
|
1773
1772
|
|
|
1774
|
-
|
|
1773
|
+
async suggest(ideaType, details) {
|
|
1775
1774
|
if (!ideaType) return console.error('ideaType (1st argument) not supplied'
|
|
1776
1775
|
+ '(e.g. \'gifts\', \'names\', \'recipes\', etc.)');
|
|
1777
1776
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
@@ -1782,7 +1781,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1782
1781
|
return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest');
|
|
1783
1782
|
},
|
|
1784
1783
|
|
|
1785
|
-
speak
|
|
1784
|
+
speak(msg, options = {}) {
|
|
1786
1785
|
// Usage example: chatgpt.speak(await chatgpt.getLastResponse(), { voice: 1, pitch: 2, speed: 3 })
|
|
1787
1786
|
// options.voice = index of voices available on user device
|
|
1788
1787
|
// options.pitch = float for pitch of speech from 0 to 2
|
|
@@ -1809,7 +1808,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1809
1808
|
} catch (err) { console.error( err); }
|
|
1810
1809
|
},
|
|
1811
1810
|
|
|
1812
|
-
|
|
1811
|
+
async summarize(text) {
|
|
1813
1812
|
if (!text) return console.error('Text (1st) argument not supplied. Pass some text!');
|
|
1814
1813
|
if (typeof text !== 'string') return console.error('Text argument must be a string!');
|
|
1815
1814
|
chatgpt.send('Summarize the following text:\n\n' + text);
|
|
@@ -1818,9 +1817,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1818
1817
|
return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest');
|
|
1819
1818
|
},
|
|
1820
1819
|
|
|
1821
|
-
toggleScheme
|
|
1820
|
+
toggleScheme() { chatgpt.settings.scheme.toggle(); },
|
|
1822
1821
|
|
|
1823
|
-
|
|
1822
|
+
async translate(text, outputLang) {
|
|
1824
1823
|
if (!text) return console.error('Text (1st) argument not supplied. Pass some text!');
|
|
1825
1824
|
if (!outputLang) return console.error('outputLang (2nd) argument not supplied. Pass a language!');
|
|
1826
1825
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
@@ -1832,9 +1831,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1832
1831
|
return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest');
|
|
1833
1832
|
},
|
|
1834
1833
|
|
|
1835
|
-
unminify
|
|
1834
|
+
unminify() { chatgpt.code.unminify(); },
|
|
1836
1835
|
|
|
1837
|
-
uuidv4
|
|
1836
|
+
uuidv4() {
|
|
1838
1837
|
let d = new Date().getTime(); // get current timestamp in ms (to ensure UUID uniqueness)
|
|
1839
1838
|
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
1840
1839
|
const r = ( // generate random nibble
|
|
@@ -1845,7 +1844,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1845
1844
|
return uuid;
|
|
1846
1845
|
},
|
|
1847
1846
|
|
|
1848
|
-
writeCode
|
|
1847
|
+
writeCode() { chatgpt.code.write(); }
|
|
1849
1848
|
};
|
|
1850
1849
|
|
|
1851
1850
|
chatgpt.scheme = { ...chatgpt.settings.scheme }; // copy `chatgpt.settings.scheme` methods into `chatgpt.scheme`
|