@kudoai/chatgpt.js 2.9.2 → 3.0.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/chatgpt.js CHANGED
@@ -3,8 +3,13 @@
3
3
  // User guide: https://chatgptjs.org/userguide
4
4
  // Latest minified release: https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js/chatgpt.min.js
5
5
 
6
- // Init endpoints
7
- const endpoints = {
6
+ // Init feedback props
7
+ localStorage.alertQueue = JSON.stringify([]);
8
+ localStorage.notifyProps = JSON.stringify({ queue: { topRight: [], bottomRight: [], bottomLeft: [], topLeft: [] }});
9
+
10
+ // Define chatgpt API
11
+ const chatgpt = { // eslint-disable-line no-redeclare
12
+ openAIaccessToken: {}, endpoints: {
8
13
  assets: 'https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js',
9
14
  openAI: {
10
15
  session: 'https://chatgpt.com/api/auth/session',
@@ -13,16 +18,7 @@ const endpoints = {
13
18
  share_create: 'https://chatgpt.com/backend-api/share/create',
14
19
  share: 'https://chatgpt.com/backend-api/share',
15
20
  instructions: 'https://chatgpt.com/backend-api/user_system_messages'
16
- }
17
- };
18
-
19
- // Init feedback properties
20
- localStorage.alertQueue = JSON.stringify([]);
21
- localStorage.notifyProps = JSON.stringify({ queue: { topRight: [], bottomRight: [], bottomLeft: [], topLeft: [] }});
22
-
23
- // Define chatgpt.methods
24
- const chatgpt = { // eslint-disable-line no-redeclare
25
- openAIaccessToken: {},
21
+ }},
26
22
 
27
23
  actAs: function(persona) {
28
24
  // Prompts ChatGPT to act as a persona from https://github.com/KudoAI/chat-prompts/blob/main/personas.json
@@ -127,8 +123,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
127
123
  + 'background-color: ' + ( scheme == 'dark' ? '#00cfff' : '#9cdaff' ) + ';'
128
124
  + 'box-shadow: 2px 1px ' + ( scheme == 'dark' ? '54px #00cfff' : '30px #9cdaff' ) + '}'
129
125
  + '.modal-close-btn {'
130
- + 'cursor: pointer ; width: 20px ; height: 20px ; float: right ; position: relative ; right: -2px }'
131
- + '.modal-close-btn svg { margin: 5px 5px }' // center SVG for hover overlay
126
+ + 'cursor: pointer ; width: 29px ; height: 29px ; border-radius: 17px ;'
127
+ + 'float: right ; position: relative ; right: -6px ; top: -5px }'
128
+ + '.modal-close-btn svg { margin: 10px }' // center SVG for hover underlay
132
129
  + `.modal-close-btn:hover { background-color: #f2f2f2${ scheme == 'dark' ? '00' : '' }}`
133
130
 
134
131
  // Checkbox styles
@@ -226,7 +223,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
226
223
  modalContainer.style.display = '';
227
224
  setTimeout(() => { // delay non-0 opacity's for transition fx
228
225
  modalContainer.style.backgroundColor = (
229
- `rgba(67, 70, 72, ${ scheme === 'dark' ? 0.62 : 0 })`);
226
+ `rgba(67, 70, 72, ${ scheme === 'dark' ? 0.62 : 0.1 })`);
230
227
  modalContainer.classList.add('animated'); }, 100);
231
228
  }
232
229
 
@@ -234,13 +231,15 @@ const chatgpt = { // eslint-disable-line no-redeclare
234
231
  const clickHandler = event => { // explicitly defined to support removal post-dismissal
235
232
  if (event.target == event.currentTarget || event.target instanceof SVGPathElement) dismissAlert(); };
236
233
  const keyHandler = event => { // to dismiss active alert
237
- const dismissKeys = [13, 27]; // enter/esc
238
- if (dismissKeys.includes(event.keyCode)) {
234
+ const dismissKeys = [' ', 'Spacebar', 'Enter', 'Return', 'Escape', 'Esc'],
235
+ dismissKeyCodes = [32, 13, 27];
236
+ if (dismissKeys.includes(event.key) || dismissKeyCodes.includes(event.keyCode)) {
239
237
  for (const alertId of alertQueue) { // look to handle only if triggering alert is active
240
238
  const alert = document.getElementById(alertId);
241
239
  if (alert && alert.style.display !== 'none') { // active alert found
242
- if (event.keyCode === 27) dismissAlert(); // if esc pressed, dismiss alert & do nothing
243
- else if (event.keyCode === 13) { // else if enter pressed
240
+ if (event.key.includes('Esc') || event.keyCode == 27) // esc pressed
241
+ dismissAlert(); // dismiss alert & do nothing
242
+ else if ([' ', 'Spacebar', 'Enter', 'Return'].includes(event.key) || [32, 13].includes(event.keyCode)) { // space/enter pressed
244
243
  const mainButton = alert.querySelector('.modal-buttons').lastChild; // look for main button
245
244
  if (mainButton) { mainButton.click(); event.preventDefault(); } // click if found
246
245
  } return;
@@ -363,7 +362,10 @@ const chatgpt = { // eslint-disable-line no-redeclare
363
362
 
364
363
  isLightMode: function() { return window.matchMedia?.('(prefers-color-scheme: light)')?.matches; },
365
364
  isDarkMode: function() { return window.matchMedia?.('(prefers-color-scheme: dark)')?.matches; },
366
- isChromium: function() { return navigator.userAgent.includes('Chrome'); },
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'); },
367
369
  isFirefox: function() { return navigator.userAgent.includes('Firefox'); },
368
370
 
369
371
  isFullScreen: function() {
@@ -377,49 +379,20 @@ const chatgpt = { // eslint-disable-line no-redeclare
377
379
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); }
378
380
  },
379
381
 
380
- clearChats: async function(method) {
381
-
382
- // Validate method arg
383
- const validMethods = ['api', 'dom'];
384
- method = (method || 'dom').trim().toLowerCase(); // set to 'dom' by default
385
- if (method && !validMethods.includes(method))
386
- return console.error(`Method argument must be one of: [${validMethods}]`);
387
-
388
- if (method == 'dom') {
389
- const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
390
- try {
391
- chatgpt.menu.open(); await delay(10);
392
- const settingsBtn = document.querySelector(
393
- 'a[role="menuitem"] svg path[d*="M12.003 10.5a1.5"]').parentNode.parentNode;
394
- settingsBtn.click(); await delay(333);
395
- const settingsBtns = document.querySelectorAll('[id*=radix] button'),
396
- deleteBtn = settingsBtns[settingsBtns.length - 1];
397
- deleteBtn.click(); await delay(10);
398
- document.querySelector('button[class*="danger"').click(); // confirm clear
399
- return console.info('Chats successfully cleared.');
400
- } catch (err) {
401
- console.error(err.message);
402
- if (arguments.length == 0) {
403
- console.info('Using backend API method instead.'); chatgpt.clearChats('api'); }
404
- }
405
-
406
- } else { // API method
407
- // NOTE: DOM is not updated to reflect new empty chat list (until session refresh)
408
-
409
- return new Promise((resolve, reject) => {
410
- chatgpt.getAccessToken().then(token => {
411
- const xhr = new XMLHttpRequest();
412
- xhr.open('PATCH', endpoints.openAI.chats, true);
413
- xhr.setRequestHeader('Content-Type', 'application/json');
414
- xhr.setRequestHeader('Authorization', 'Bearer ' + token);
415
- xhr.onload = () => {
416
- if (xhr.status !== 200) return reject('🤖 chatgpt.js >> Request failed. Cannot clear chats.');
417
- console.info('Chats successfully cleared'); resolve();
418
- };
419
- xhr.send(JSON.stringify({ is_visible: false }));
420
- }).catch(err => reject(new Error(err.message)));
421
- });
422
- }
382
+ clearChats: async function() { // back-end method
383
+ return new Promise((resolve, reject) => {
384
+ chatgpt.getAccessToken().then(token => {
385
+ const xhr = new XMLHttpRequest();
386
+ xhr.open('PATCH', chatgpt.endpoints.openAI.chats, true);
387
+ xhr.setRequestHeader('Content-Type', 'application/json');
388
+ xhr.setRequestHeader('Authorization', 'Bearer ' + token);
389
+ xhr.onload = () => {
390
+ if (xhr.status !== 200) return reject('🤖 chatgpt.js >> Request failed. Cannot clear chats.');
391
+ console.info('Chats successfully cleared'); resolve();
392
+ };
393
+ xhr.send(JSON.stringify({ is_visible: false }));
394
+ }).catch(err => reject(new Error(err.message)));
395
+ });
423
396
  },
424
397
 
425
398
  code: {
@@ -439,6 +412,34 @@ const chatgpt = { // eslint-disable-line no-redeclare
439
412
  return codeBlocks ? codeBlocks[codeBlocks.length - 1] : msg;
440
413
  },
441
414
 
415
+ isIdle: async function() {
416
+ await new Promise(resolve => { // when in conversation page
417
+ (function checkConvoPage() {
418
+ document.querySelector('div[data-message-author-role]') ? resolve(true)
419
+ : setTimeout(checkConvoPage, 200); })();
420
+ });
421
+ await new Promise(resolve => { // when reply starts generating
422
+ (function checkReplyExists() {
423
+ const msgDivs = document.querySelectorAll('div[data-message-author-role]');
424
+ msgDivs[msgDivs.length - 1].dataset.messageAuthorRole == 'assistant' ? resolve(true)
425
+ : setTimeout(checkReplyExists, 200); })();
426
+ });
427
+ const lastReplyDiv = await new Promise(resolve => { // when code starts generating
428
+ (function checkPreExists() {
429
+ const replyDivs = document.querySelectorAll('div[data-message-author-role="assistant"]'),
430
+ lastReplyDiv = replyDivs[replyDivs.length - 1];
431
+ lastReplyDiv.querySelector('pre') ? resolve(lastReplyDiv)
432
+ : setTimeout(checkPreExists, 200); })();
433
+ });
434
+ return Promise.race([
435
+ new Promise(resolve => { // when code block not last child of reply div
436
+ (function checkPreNotLast() {
437
+ lastReplyDiv.querySelector('pre').nextElementSibling ? resolve(true)
438
+ : setTimeout(checkPreNotLast, 200); })();
439
+ }), chatgpt.isIdle() // ...or reply stopped generating
440
+ ]);
441
+ },
442
+
442
443
  minify: async function(code) {
443
444
  if (!code) return console.error('Code argument not supplied. Pass some code!');
444
445
  if (typeof code !== 'string') return console.error('Code argument must be a string!');
@@ -609,6 +610,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
609
610
  },
610
611
 
611
612
  extractCode: function() { chatgpt.code.extract(); },
613
+ focusChatbar: function() { chatgpt.getChatBox()?.focus(); },
612
614
 
613
615
  generateRandomIP: function() {
614
616
  const ip = Array.from({length: 4}, () => Math.floor(chatgpt.randomFloat() * 256)).join('.');
@@ -625,9 +627,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
625
627
  throw new TypeError('Invalid arguments. Both arguments must be strings.'); }
626
628
 
627
629
  // Validate targetType
628
- if (!targetTypes.includes(targetType.toLowerCase())) {
630
+ if (!cjsTargetTypes.includes(targetType.toLowerCase())) {
629
631
  throw new Error('Invalid targetType: ' + targetType
630
- + '. Valid values are: ' + JSON.stringify(targetTypes)); }
632
+ + '. Valid values are: ' + JSON.stringify(cjsTargetTypes)); }
631
633
 
632
634
  // Validate targetName scoped to pre-validated targetType
633
635
  const targetNames = [], reTargetName = new RegExp('^get(.*)' + targetType + '$', 'i');
@@ -655,7 +657,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
655
657
  (Date.parse(chatgpt.openAIaccessToken.expireDate) - Date.parse(new Date()) >= 0)) // not expired
656
658
  return resolve(chatgpt.openAIaccessToken.token);
657
659
  const xhr = new XMLHttpRequest();
658
- xhr.open('GET', endpoints.openAI.session, true);
660
+ xhr.open('GET', chatgpt.endpoints.openAI.session, true);
659
661
  xhr.setRequestHeader('Content-Type', 'application/json');
660
662
  xhr.onload = () => {
661
663
  if (xhr.status !== 200) return reject('🤖 chatgpt.js >> Request failed. Cannot retrieve access token.');
@@ -688,7 +690,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
688
690
  // Return account details
689
691
  return new Promise((resolve, reject) => {
690
692
  const xhr = new XMLHttpRequest();
691
- xhr.open('GET', endpoints.openAI.session, true);
693
+ xhr.open('GET', chatgpt.endpoints.openAI.session, true);
692
694
  xhr.setRequestHeader('Content-Type', 'application/json');
693
695
  xhr.onload = () => {
694
696
  if (xhr.status === 200) {
@@ -744,7 +746,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
744
746
  const re_chatID = /\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/;
745
747
  return new Promise((resolve, reject) => {
746
748
  const xhr = new XMLHttpRequest();
747
- xhr.open('GET', endpoints.openAI.chats, true);
749
+ xhr.open('GET', chatgpt.endpoints.openAI.chats, true);
748
750
  xhr.setRequestHeader('Content-Type', 'application/json');
749
751
  xhr.setRequestHeader('Authorization', 'Bearer ' + token);
750
752
  xhr.onload = () => {
@@ -784,7 +786,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
784
786
  return new Promise((resolve, reject) => {
785
787
  const xhr = new XMLHttpRequest();
786
788
  getChatDetails(token, ['id']).then(chat => {
787
- xhr.open('GET', `${endpoints.openAI.chat}/${chat.id}`, true);
789
+ xhr.open('GET', `${chatgpt.endpoints.openAI.chat}/${chat.id}`, true);
788
790
  xhr.setRequestHeader('Content-Type', 'application/json');
789
791
  xhr.setRequestHeader('Authorization', 'Bearer ' + token);
790
792
  xhr.onload = () => {
@@ -869,7 +871,8 @@ const chatgpt = { // eslint-disable-line no-redeclare
869
871
 
870
872
  getNewChatButton: function() {
871
873
  for (const navBtnSVG of document.querySelectorAll('nav button svg'))
872
- if (navBtnSVG.querySelector('path[d*="M15.673 3.913a3.121"]')) // new chat icon found
874
+ if (navBtnSVG.querySelector('path[d*="M15.673 3.913a3.121"], ' // pencil-on-pad icon
875
+ + 'path[d*="M3.07 10.876C3.623"]')) // refresh icon if temp chat
873
876
  return navBtnSVG.parentNode;
874
877
  },
875
878
 
@@ -916,8 +919,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
916
919
  isLoaded: function() {
917
920
  return new Promise(resolve => {
918
921
  (function checkChatHistory() {
919
- if (document.querySelector('nav')) resolve(true);
920
- else setTimeout(checkChatHistory, 100);
922
+ document.querySelector('nav') ? resolve(true) : setTimeout(checkChatHistory, 200);
921
923
  })();
922
924
  });}
923
925
  },
@@ -995,7 +997,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
995
997
 
996
998
  return new Promise((resolve, reject) => {
997
999
  const xhr = new XMLHttpRequest();
998
- xhr.open(method, endpoints.openAI.instructions, true);
1000
+ xhr.open(method, chatgpt.endpoints.openAI.instructions, true);
999
1001
  // Set headers
1000
1002
  xhr.setRequestHeader('Accept-Language', 'en-US');
1001
1003
  xhr.setRequestHeader('Authorization', 'Bearer ' + token);
@@ -1047,29 +1049,24 @@ const chatgpt = { // eslint-disable-line no-redeclare
1047
1049
  }
1048
1050
  },
1049
1051
 
1050
- isChromium: function() { return chatgpt.browser.isChromium(); },
1051
1052
  isDarkMode: function() { return document.documentElement.classList.toString().includes('dark'); },
1052
- isFirefox: function() { return chatgpt.browser.isFirefox(); },
1053
1053
  isFullScreen: function() { return chatgpt.browser.isFullScreen(); },
1054
1054
 
1055
1055
  isIdle: function() {
1056
1056
  return new Promise(resolve => {
1057
1057
  (function checkIsIdle() {
1058
- if (chatgpt.getRegenerateButton()) resolve(true);
1059
- else setTimeout(checkIsIdle, 100);
1058
+ chatgpt.getRegenerateButton() ? resolve(true) : setTimeout(checkIsIdle, 200);
1060
1059
  })();
1061
1060
  });},
1062
1061
 
1063
1062
  isLoaded: function() {
1064
1063
  return new Promise(resolve => {
1065
1064
  (function checkIsLoaded() {
1066
- if (chatgpt.getNewChatButton()) resolve(true);
1067
- else setTimeout(checkIsLoaded, 100);
1065
+ chatgpt.getNewChatButton() ? resolve(true) : setTimeout(checkIsLoaded, 200);
1068
1066
  })();
1069
1067
  });},
1070
1068
 
1071
1069
  isLightMode: function() { return document.documentElement.classList.toString().includes('light'); },
1072
- isMobileDevice: function() { return chatgpt.browser.isMobile(); },
1073
1070
 
1074
1071
  logout: function() { window.location.href = 'https://chat.openai.com/auth/logout'; },
1075
1072
 
@@ -1105,7 +1102,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
1105
1102
  const icon = document.createElement('img');
1106
1103
  icon.src = attrs?.icon && typeof attrs.icon == 'string' // can also be base64 encoded image string
1107
1104
  ? attrs.icon // add icon to button element if given, else default one
1108
- : ( endpoints.assets + '/starters/chrome/extension/icons/icon128.png' );
1105
+ : ( chatgpt.endpoints.assets + '/starters/chrome/extension/icons/icon128.png' );
1109
1106
  icon.width = 18;
1110
1107
  newElement.insertBefore(icon, newElement.firstChild);
1111
1108
 
@@ -1176,7 +1173,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
1176
1173
 
1177
1174
  notify: async function(msg, position, notifDuration, shadow) {
1178
1175
  notifDuration = notifDuration ? +notifDuration : 1.75; // sec duration to maintain notification visibility
1179
- const fadeDuration = 0.3, // sec duration of fade-out
1176
+ const fadeDuration = 0.35, // sec duration of fade-out
1180
1177
  vpYoffset = 23, vpXoffset = 27; // px offset from viewport border
1181
1178
 
1182
1179
  // Create/append notification div
@@ -1559,7 +1556,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
1559
1556
  return new Promise((resolve, reject) => {
1560
1557
  const xhr = new XMLHttpRequest();
1561
1558
  chatgpt.getChatData(chatToGet).then(chat => {
1562
- xhr.open('GET', `${ endpoints.openAI.chat }/${ chat.id }`, true);
1559
+ xhr.open('GET', `${ chatgpt.endpoints.openAI.chat }/${ chat.id }`, true);
1563
1560
  xhr.setRequestHeader('Content-Type', 'application/json');
1564
1561
  xhr.setRequestHeader('Authorization', 'Bearer ' + token);
1565
1562
  xhr.onload = () => {
@@ -1574,7 +1571,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
1574
1571
  return new Promise((resolve, reject) => {
1575
1572
  const xhr = new XMLHttpRequest();
1576
1573
  chatgpt.getChatData(chatToGet).then(chat => {
1577
- xhr.open('POST', endpoints.openAI.share_create, true);
1574
+ xhr.open('POST', chatgpt.endpoints.openAI.share_create, true);
1578
1575
  xhr.setRequestHeader('Content-Type', 'application/json');
1579
1576
  xhr.setRequestHeader('Authorization', 'Bearer ' + token);
1580
1577
  xhr.onload = () => {
@@ -1592,7 +1589,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
1592
1589
  const confirmShareChat = (token, data) => {
1593
1590
  return new Promise((resolve, reject) => {
1594
1591
  const xhr = new XMLHttpRequest();
1595
- xhr.open('PATCH', `${ endpoints.openAI.share }/${ data.share_id }`, true);
1592
+ xhr.open('PATCH', `${ chatgpt.endpoints.openAI.share }/${ data.share_id }`, true);
1596
1593
  xhr.setRequestHeader('Content-Type', 'application/json');
1597
1594
  xhr.setRequestHeader('Authorization', 'Bearer ' + token);
1598
1595
  xhr.onload = () => {
@@ -1702,7 +1699,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
1702
1699
  const icon = document.createElement('img');
1703
1700
  icon.src = attrs?.icon && typeof attrs.icon == 'string' // Can also be base64 encoded image string
1704
1701
  ? attrs.icon // Add icon to button element if given, else default one
1705
- : ( endpoints.assets + '/starters/chrome/extension/icons/icon128.png' );
1702
+ : ( chatgpt.endpoints.assets + '/starters/chrome/extension/icons/icon128.png' );
1706
1703
  icon.width = 18;
1707
1704
  newElement.insertBefore(icon, newElement.firstChild);
1708
1705
 
@@ -1751,23 +1748,24 @@ const chatgpt = { // eslint-disable-line no-redeclare
1751
1748
 
1752
1749
  toggle: function() {
1753
1750
  const isMobileDevice = chatgpt.browser.isMobile(),
1754
- isGPT4oUI = !!document.documentElement.className.includes(' '),
1755
- navBtnSelector = isMobileDevice ? '#__next button' : isGPT4oUI ? 'nav button' : 'main button',
1751
+ navBtnSelector = isMobileDevice ? '#__next button' : 'nav button',
1756
1752
  isToggleBtn = isMobileDevice ? () => true // since 1st one is toggle
1757
- : isGPT4oUI ? btn => btn.querySelectorAll('svg path[d*="M8.857 3h6.286c1.084"]').length > 0
1758
- : /* post-GPT-4o desktop */ btn => [...btn.querySelectorAll('*')]
1759
- .some(child => child.style.transform.includes('translateY'));
1753
+ : btn => btn.querySelectorAll('svg path[d*="M8.857 3h6.286c1.084"]').length > 0;
1760
1754
  for (const btn of document.querySelectorAll(navBtnSelector))
1761
1755
  if (isToggleBtn(btn)) { btn.click(); return; }
1762
1756
  },
1763
1757
 
1764
- isLoaded: function() {
1765
- return new Promise(resolve => {
1766
- (function checkIsLoaded() {
1767
- if (document.querySelector('nav a[href="/"]')) resolve(true);
1768
- else setTimeout(checkIsLoaded, 100);
1769
- })();
1770
- });}
1758
+ isLoaded: async function() {
1759
+ await chatgpt.isLoaded();
1760
+ return Promise.race([
1761
+ new Promise(resolve => {
1762
+ (function checkNewChatLink() {
1763
+ chatgpt.getNewChatLink() ? resolve(true) : setTimeout(checkNewChatLink, 200);
1764
+ })();
1765
+ }),
1766
+ new Promise(resolve => setTimeout(resolve, 5000)) // since New Chat link not always present
1767
+ ]);
1768
+ }
1771
1769
  },
1772
1770
 
1773
1771
  startNewChat: function() { try { chatgpt.getNewChatBtn().click(); } catch (err) { console.error(err.message); }},
@@ -1853,9 +1851,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
1853
1851
  chatgpt.scheme = { ...chatgpt.settings.scheme }; // copy `chatgpt.settings.scheme` methods into `chatgpt.scheme`
1854
1852
 
1855
1853
  // Create chatgpt.[actions]Button(identifier) functions
1856
- const buttonActions = ['click', 'get'], targetTypes = [ 'button', 'link', 'div', 'response' ];
1857
- for (const buttonAction of buttonActions) {
1858
- chatgpt[buttonAction + 'Button'] = function handleButton(buttonIdentifier) {
1854
+ const cjsBtnActions = ['click', 'get'], cjsTargetTypes = [ 'button', 'link', 'div', 'response' ];
1855
+ for (const btnAction of cjsBtnActions) {
1856
+ chatgpt[btnAction + 'Button'] = function handleButton(buttonIdentifier) {
1859
1857
  const button = /^[.#]/.test(buttonIdentifier) ? document.querySelector(buttonIdentifier)
1860
1858
  : /send/i.test(buttonIdentifier) ? document.querySelector('form button[class*="bottom"]')
1861
1859
  : /scroll/i.test(buttonIdentifier) ? document.querySelector('button[class*="cursor"]')
@@ -1866,12 +1864,12 @@ for (const buttonAction of buttonActions) {
1866
1864
  for (const navLink of document.querySelectorAll('nav a')) { // try nav links if no button
1867
1865
  if (navLink.textContent.toLowerCase().includes(buttonIdentifier.toLowerCase())) {
1868
1866
  return navLink; }}})();
1869
- if (buttonAction == 'click') { button.click(); } else { return button; }
1867
+ if (btnAction == 'click') { button.click(); } else { return button; }
1870
1868
  };
1871
1869
  }
1872
1870
 
1873
1871
  // Create alias functions
1874
- const funcAliases = [
1872
+ const cjsFuncAliases = [
1875
1873
  ['actAs', 'actas', 'act', 'become', 'persona', 'premadePrompt', 'preMadePrompt', 'prePrompt', 'preprompt', 'roleplay', 'rolePlay', 'rp'],
1876
1874
  ['activateAutoRefresh', 'activateAutoRefresher', 'activateRefresher', 'activateSessionRefresher',
1877
1875
  'autoRefresh', 'autoRefresher', 'autoRefreshSession', 'refresher', 'sessionRefresher'],
@@ -1911,7 +1909,7 @@ const funcAliases = [
1911
1909
  ['unminify', 'unminifyCode', 'codeUnminify'],
1912
1910
  ['writeCode', 'codeWrite']
1913
1911
  ];
1914
- const synonyms = [
1912
+ const cjsFuncSynonyms = [
1915
1913
  ['account', 'acct'],
1916
1914
  ['activate', 'turnOn'],
1917
1915
  ['analyze', 'check', 'evaluate', 'review'],
@@ -1924,6 +1922,7 @@ const synonyms = [
1924
1922
  ['data', 'details'],
1925
1923
  ['deactivate', 'deActivate', 'turnOff'],
1926
1924
  ['execute', 'interpret', 'interpreter', 'run'],
1925
+ ['firefox', 'ff'],
1927
1926
  ['generating', 'generation'],
1928
1927
  ['minify', 'uglify'],
1929
1928
  ['refactor', 'rewrite'],
@@ -1940,7 +1939,7 @@ const camelCaser = (words) => {
1940
1939
  for (const prop in chatgpt) {
1941
1940
 
1942
1941
  // Create new function for each alias
1943
- for (const subAliases of funcAliases) {
1942
+ for (const subAliases of cjsFuncAliases) {
1944
1943
  if (subAliases.includes(prop)) {
1945
1944
  if (subAliases.some(element => element.includes('.'))) {
1946
1945
  const nestedFunction = subAliases.find(element => element.includes('.')).split('.')[1];
@@ -1960,7 +1959,7 @@ for (const prop in chatgpt) {
1960
1959
  if (typeof chatgpt[funcName] == 'function') {
1961
1960
  const funcWords = funcName.split(/(?=[A-Zs])/); // split function name into constituent words
1962
1961
  for (const funcWord of funcWords) {
1963
- const synonymValues = [].concat(...synonyms // flatten into single array w/ word's synonyms
1962
+ const synonymValues = [].concat(...cjsFuncSynonyms // flatten into single array w/ word's cjsFuncSynonyms
1964
1963
  .filter(arr => arr.includes(funcWord.toLowerCase())) // filter in relevant synonym sub-arrays
1965
1964
  .map(arr => arr.filter(synonym => synonym !== funcWord.toLowerCase()))); // filter out matching word
1966
1965
  for (const synonym of synonymValues) { // create function per synonym