@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/chatgpt.js CHANGED
@@ -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: function(persona) {
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: function() {
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: function() {
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: function(title, msg, btns, checkbox, width) {
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
- askAndGetReply: async function(query) {
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: function(interval) {
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: function() {
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: function() {
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: function() {
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: function() {
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: function() { return window.matchMedia?.('(prefers-color-scheme: light)')?.matches; },
364
- isDarkMode: function() { return window.matchMedia?.('(prefers-color-scheme: dark)')?.matches; },
365
- isChromium: function() { return !!JSON.stringify(navigator.userAgentData?.brands)?.includes('Chromium'); },
366
- isChrome: function() { return !!JSON.stringify(navigator.userAgentData?.brands)?.includes('Chrome'); },
367
- isEdge: function() { return !!JSON.stringify(navigator.userAgentData?.brands)?.includes('Edge'); },
368
- isBrave: function() { return !!JSON.stringify(navigator.userAgentData?.brands)?.includes('Brave'); },
369
- isFirefox: function() { return navigator.userAgent.includes('Firefox'); },
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: function() {
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: function() {
378
+ isMobile() {
379
379
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); }
380
380
  },
381
381
 
382
- clearChats: async function() { // back-end method
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
- execute: async function(code) {
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: function(msg) { // extract pure code from response (targets last block)
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
- isIdle: async function() {
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
- minify: async function(code) {
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
- obfuscate: async function(code) {
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
- refactor: async function(code, objective) {
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
- review: async function(code) {
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
- unminify: async function(code) {
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
- write: async function(prompt, outputLang) {
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: function() { chatgpt.response.continue(); },
501
+ continue() { chatgpt.response.continue(); },
502
502
 
503
- detectLanguage: async function(text) {
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: function() { chatgpt.code.execute(); },
513
+ executeCode() { chatgpt.code.execute(); },
514
514
 
515
- exportChat: async function(chatToGet, format) {
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: function() { chatgpt.code.extract(); },
613
- focusChatbar: function() { chatgpt.getChatBox()?.focus(); },
612
+ extractCode() { chatgpt.code.extract(); },
613
+ focusChatbar() { chatgpt.getChatBox()?.focus(); },
614
614
 
615
- generateRandomIP: function() {
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: function(targetType, targetName = '') {
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: function() {
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: function(...details) {
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: function() { return document.getElementById('prompt-textarea'); },
706
+ getChatBox() { return document.getElementById('prompt-textarea'); },
707
707
 
708
- getChatData: function(chatToGet = 1, detailsToGet = 'all', sender = 'all', msgToGet = 'all') {
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: function() { return chatgpt.getChatBox().value; },
859
+ getChatInput() { return chatgpt.getChatBox().value; },
860
860
 
861
- getContinueGeneratingButton: function() {
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: function() { return document.querySelector('main form').parentNode.parentNode.nextElementSibling; },
868
- getHeaderDiv: function() { return document.querySelector('main .sticky'); },
869
- getLastPrompt: function() { return chatgpt.getChatData('active', 'msg', 'user', 'latest'); },
870
- getLastResponse: function() { return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'); },
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: function() {
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: function() { return document.querySelector('nav a[href="/"]'); },
879
+ getNewChatLink() { return document.querySelector('nav a[href="/"]'); },
880
880
 
881
- getRegenerateButton: function() {
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: function() {
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: function(chatToGet, responseToGet) { return chatgpt.response.getFromAPI(chatToGet, responseToGet); },
897
- getResponseFromDOM: function(pos) { return chatgpt.response.getFromDOM(pos); },
898
- getScrollToBottomButton: function() { return document.querySelector('button[class*="cursor"][class*="bottom"]'); },
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: function() {
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: function() {
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: function() {
911
+ getUserLanguage() {
912
912
  return navigator.languages[0] || navigator.language || navigator.browserLanguage ||
913
913
  navigator.systemLanguage || navigator.userLanguage || ''; },
914
914
 
915
- hideFooter: function() { chatgpt.getFooterDiv().style.display = 'none'; },
916
- hideHeader: function() { chatgpt.getHeaderDiv().style.display = 'none'; },
915
+ hideFooter() { chatgpt.getFooterDiv().style.display = 'none'; },
916
+ hideHeader() { chatgpt.getHeaderDiv().style.display = 'none'; },
917
917
 
918
918
  history: {
919
- isLoaded: function() {
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: function(instruction, target) {
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: function(target) {
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: function() {
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: function(method, token, body) {
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: function() {
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: function() {
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: function() {
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: function() { return document.documentElement.classList.toString().includes('dark'); },
1053
- isFullScreen: function() { return chatgpt.browser.isFullScreen(); },
1052
+ isDarkMode() { return document.documentElement.classList.toString().includes('dark'); },
1053
+ isFullScreen() { return chatgpt.browser.isFullScreen(); },
1054
1054
 
1055
- isIdle: function() {
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: function() {
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: function() { return document.documentElement.classList.toString().includes('light'); },
1069
+ isLightMode() { return document.documentElement.classList.toString().includes('light'); },
1070
1070
 
1071
- logout: function() { window.location.href = 'https://chat.openai.com/auth/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: function(element, attrs = {}) {
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: function() {
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: function() {
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: function() { chatgpt.code.minify(); },
1172
+ minify() { chatgpt.code.minify(); },
1173
1173
 
1174
- notify: async function(msg, position, notifDuration, shadow) {
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: function() { chatgpt.code.obfuscate(); },
1284
+ obfuscate() { chatgpt.code.obfuscate(); },
1285
1285
 
1286
- printAllFunctions: function() {
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: function() {
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: function() { chatgpt.code.refactor(); },
1359
- regenerate: function() { chatgpt.response.regenerate(); },
1358
+ refactor() { chatgpt.code.refactor(); },
1359
+ regenerate() { chatgpt.response.regenerate(); },
1360
1360
 
1361
- renderHTML: function(node) {
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
- resend: async function() { chatgpt.send(await chatgpt.getChatData('latest', 'msg', 'user', 'latest')); },
1412
+ async resend() { chatgpt.send(await chatgpt.getChatData('latest', 'msg', 'user', 'latest')); },
1413
1413
 
1414
1414
  response: {
1415
- continue: function() { try { chatgpt.getContinueBtn().click(); } catch (err) { console.error(err.message); }},
1415
+ continue() { try { chatgpt.getContinueBtn().click(); } catch (err) { console.error(err.message); }},
1416
1416
 
1417
- get: function() {
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: function(chatToGet, responseToGet) {
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: function(pos) {
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: function() { return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'); },
1474
- regenerate: function() { try { chatgpt.getRegenerateBtn().click(); } catch (err) { console.error(err.message); }},
1475
- stopGenerating: function() { try { chatgpt.getStopBtn().click(); } catch (err) { console.error(err.message); }}
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: function() { chatgpt.code.review(); },
1479
- scrollToBottom: function() { try { chatgpt.getScrollBtn().click(); } catch (err) { console.error(err.message); }},
1478
+ reviewCode() { chatgpt.code.review(); },
1479
+ scrollToBottom() { try { chatgpt.getScrollBtn().click(); } catch (err) { console.error(err.message); }},
1480
1480
 
1481
- send: function(msg, method='') {
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', { keyCode: 13, bubbles: true }));
1493
- } else setTimeout(delaySend, 25);
1494
- }, 25);
1491
+ : textArea.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
1492
+ } else setTimeout(delaySend, 222);
1493
+ }, 222);
1495
1494
  },
1496
1495
 
1497
- sendInNewChat: function(msg) {
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: function() { return document.documentElement.classList.contains('dark'); },
1508
- isLight: function() { return document.documentElement.classList.contains('light'); },
1509
- set: function(value) {
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: function() {
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
- sentiment: async function(text, entity) {
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: function(value) { chatgpt.settings.scheme.set(value); },
1544
+ setScheme(value) { chatgpt.settings.scheme.set(value); },
1546
1545
 
1547
- shareChat: function(chatToGet, method = 'clipboard') {
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: function() { chatgpt.getFooterDiv().style.display = 'revert'; },
1627
- showHeader: function() { chatgpt.getHeaderDiv().style.display = 'flex'; },
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: function() {
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: function(element, attrs = {}) {
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: function() { this.isOn() ? this.toggle() : console.info('Sidebar already hidden!'); },
1740
- show: function() { this.isOff() ? this.toggle() : console.info('Sidebar already shown!'); },
1741
- isOff: function() { return !this.isOn(); },
1742
- isOn: function() {
1743
- const sidebar = document.querySelector('#__next > div > div');
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: function() {
1748
+ toggle() {
1750
1749
  const isMobileDevice = chatgpt.browser.isMobile(),
1751
- navBtnSelector = isMobileDevice ? '#__next button' : 'nav button',
1750
+ navBtnSelector = isMobileDevice ? 'button' : 'nav button',
1752
1751
  isToggleBtn = isMobileDevice ? () => true // since 1st one is toggle
1753
- : btn => btn.querySelectorAll('svg path[d*="M8.857 3h6.286c1.084"]').length > 0;
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
- isLoaded: async function() {
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: function() { try { chatgpt.getNewChatBtn().click(); } catch (err) { console.error(err.message); }},
1772
- stop: function() { chatgpt.response.stopGenerating(); },
1770
+ startNewChat() { try { chatgpt.getNewChatBtn().click(); } catch (err) { console.error(err.message); }},
1771
+ stop() { chatgpt.response.stopGenerating(); },
1773
1772
 
1774
- suggest: async function(ideaType, details) {
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: function(msg, options = {}) {
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
- summarize: async function(text) {
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: function() { chatgpt.settings.scheme.toggle(); },
1820
+ toggleScheme() { chatgpt.settings.scheme.toggle(); },
1822
1821
 
1823
- translate: async function(text, outputLang) {
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: function() { chatgpt.code.unminify(); },
1834
+ unminify() { chatgpt.code.unminify(); },
1836
1835
 
1837
- uuidv4: function() {
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: function() { chatgpt.code.write(); }
1847
+ writeCode() { chatgpt.code.write(); }
1849
1848
  };
1850
1849
 
1851
1850
  chatgpt.scheme = { ...chatgpt.settings.scheme }; // copy `chatgpt.settings.scheme` methods into `chatgpt.scheme`