@kudoai/chatgpt.js 3.8.5 → 3.9.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/LICENSE.md CHANGED
@@ -26,7 +26,7 @@
26
26
 
27
27
  # MIT License
28
28
 
29
- **Copyright © 2023–2025 [KudoAI](https://github.com/KudoAI) & [contributors](.#-contributors)**
29
+ **Copyright © 2023–2026 [KudoAI](https://github.com/KudoAI) & [contributors](.#-contributors)**
30
30
 
31
31
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
32
32
 
package/README.md CHANGED
@@ -45,29 +45,25 @@
45
45
 
46
46
  <div id="shields" align="center">
47
47
 
48
- <a href="https://github.com/KudoAI/chatgpt.js/stargazers" target="_blank" rel="noopener">
49
- <img src="https://img.shields.io/github/stars/KudoAI/chatgpt.js?label=Stars&color=af68ff&logo=github&logoColor=white&labelColor=464646&style=for-the-badge"></a>
50
48
  <a href="https://github.com/KudoAI/chatgpt.js/blob/main/LICENSE.md" target="_blank" rel="noopener">
51
- <img src="https://img.shields.io/badge/License-MIT-fc4f2d.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
49
+ <img src="https://img.shields.io/badge/License-MIT-orange.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
52
50
  <a href="https://www.npmjs.com/package/@kudoai/chatgpt.js/v/latest" target="_blank" rel="noopener">
53
51
  <img src="https://img.shields.io/npm/v/%40kudoai%2Fchatgpt.js?logo=npm&logoColor=white&labelColor=464646&color=blue&style=for-the-badge&label=Latest+Release"></a>
54
- <a href="https://github.com/KudoAI/chatgpt.js/tree/v3.8.5/dist/chatgpt.min.js" target="_blank" rel="noopener">
55
- <img src="https://img.shields.io/github/size/KudoAI/chatgpt.js/dist/chatgpt.min.js?branch=v3.8.5&label=Minified%20Size&logo=databricks&logoColor=white&labelColor=464646&color=ff69b4&style=for-the-badge"></a>
52
+ <a href="https://github.com/KudoAI/chatgpt.js/tree/v3.9.0/dist/chatgpt.min.js" target="_blank" rel="noopener">
53
+ <img src="https://img.shields.io/github/size/KudoAI/chatgpt.js/dist/chatgpt.min.js?branch=v3.9.0&label=Minified%20Size&logo=databricks&logoColor=white&labelColor=464646&color=ff69b4&style=for-the-badge"></a>
56
54
  <a href="https://www.codefactor.io/repository/github/kudoai/chatgpt.js" target="_blank" rel="noopener">
57
55
  <img src="https://img.shields.io/codefactor/grade/github/kudoai/chatgpt.js?label=Code+Quality&logo=codefactor&logoColor=white&labelColor=464646&color=1acc6c&style=for-the-badge"></a>
58
56
  <a href="https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=kudoai_chatgpt.js" target="_blank" rel="noopener">
59
57
  <img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fsonarcloud.io%2Fapi%2Fmeasures%2Fcomponent%3Fcomponent%3Dkudoai_chatgpt.js%26metricKeys%3Dvulnerabilities&query=%24.component.measures.0.value&style=for-the-badge&logo=sonarcloud&logoColor=white&labelColor=464646&label=Vulnerabilities&color=gold"></a>
60
58
  <a href="https://github.com/sindresorhus/awesome-chatgpt#javascript" target="_blank" rel="noopener">
61
- <img src="https://img.shields.io/badge/Mentioned_in-Awesome-cca8c4?logo=awesomelists&logoColor=white&labelColor=464646&style=for-the-badge"></a>
62
- <a href="https://www.producthunt.com/posts/chatgpt-js" target="_blank" rel="noopener">
63
- <img src="https://img.shields.io/badge/Featured_on-Product_Hunt-ff6154?logo=producthunt&logoColor=white&labelColor=464646&style=for-the-badge"></a>
64
- <a href="https://trendshift.io/repositories/2896" target="_blank" rel="noopener">
65
- <img src="https://img.shields.io/badge/Trended-Top_20_Repository-869da0?logo=github&logoColor=white&labelColor=464646&style=for-the-badge"></a>
59
+ <img src="https://img.shields.io/badge/Mentioned_in-Awesome-af68ff?logo=awesomelists&logoColor=white&labelColor=464646&style=for-the-badge"></a>
66
60
  <a href="#">
67
61
  <img src="https://img.shields.io/badge/jsDelivr_Requests-2,000,000+-2bbbd8.svg?logo=jsdelivr&logoColor=white&labelColor=464646&style=for-the-badge"></a>
68
62
 
69
63
  </div>
70
64
 
65
+ <br><br>
66
+
71
67
  <img height=8px width="100%" src="https://assets.chatgptjs.org/images/separators/gradient-aqua.png?v=e638eac">
72
68
 
73
69
  <div id="intro">
@@ -118,7 +114,7 @@
118
114
 
119
115
  ```js
120
116
  (async () => {
121
- await import('https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.5/dist/chatgpt.min.js');
117
+ await import('https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.9.0/dist/chatgpt.min.js');
122
118
  // Your code here...
123
119
  })();
124
120
  ```
@@ -127,7 +123,7 @@
127
123
 
128
124
  ```js
129
125
  var xhr = new XMLHttpRequest();
130
- xhr.open('GET', 'https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.5/dist/chatgpt.min.js');
126
+ xhr.open('GET', 'https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.9.0/dist/chatgpt.min.js');
131
127
  xhr.onload = function () {
132
128
  if (xhr.status === 200) {
133
129
  var chatgptJS = document.createElement('script');
@@ -150,7 +146,7 @@ function yourCode() {
150
146
 
151
147
  ```js
152
148
  ...
153
- // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.5/dist/chatgpt.min.js
149
+ // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.9.0/dist/chatgpt.min.js
154
150
  // ==/UserScript==
155
151
 
156
152
  // Your code here...
@@ -220,7 +216,7 @@ chatgpt.get('reply', 'last');
220
216
 
221
217
  Each call equally fetches the last response. If you think it works, it probably will... so just type it!
222
218
 
223
- If it didn't, check out the extended [userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.8.5/docs/USERGUIDE.md), or simply submit an [issue](https://github.com/KudoAI/chatgpt.js/issues) or [PR](https://github.com/KudoAI/chatgpt.js/pulls) and it will be integrated, ezpz!
219
+ If it didn't, check out the extended [userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.9.0/docs/USERGUIDE.md), or simply submit an [issue](https://github.com/KudoAI/chatgpt.js/issues) or [PR](https://github.com/KudoAI/chatgpt.js/pulls) and it will be integrated, ezpz!
224
220
 
225
221
  <img height=8px width="100%" src="https://assets.chatgptjs.org/images/separators/gradient-aqua.png?v=e638eac">
226
222
 
@@ -482,7 +478,7 @@ This library exists thanks to code, translations, issues & ideas from the follow
482
478
  <div align="center">
483
479
 
484
480
  **[Releases](https://github.com/KudoAI/chatgpt.js/releases)** /
485
- [Userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.8.5/docs/USERGUIDE.md) /
481
+ [Userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.9.0/docs/USERGUIDE.md) /
486
482
  [Discuss](https://github.com/KudoAI/chatgpt.js/discussions) /
487
483
  [Back to top ↑](#top)
488
484
 
package/chatgpt.js CHANGED
@@ -1,12 +1,8 @@
1
- // © 2023–2025 KudoAI & contributors under the MIT license.
1
+ // © 2023–2026 KudoAI & contributors under the MIT license.
2
2
  // Source: https://github.com/KudoAI/chatgpt.js
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 feedback props
7
- localStorage.alertQueue = JSON.stringify([])
8
- localStorage.notifyProps = JSON.stringify({ queue: { topRight: [], bottomRight: [], bottomLeft: [], topLeft: [] }})
9
-
10
6
  // Define chatgpt API
11
7
  const chatgpt = {
12
8
 
@@ -25,21 +21,21 @@ const chatgpt = {
25
21
  selectors: {
26
22
  btns: {
27
23
  continue: 'button:has(svg[class*=rotate] > path[d^="M4.47189"])',
28
- createImage: 'button[data-testid=composer-create-image]',
29
- deepResearch: 'button[data-testid=composer-deep-research]',
24
+ createImage: 'button[data-testid=composer-button-create-image]',
30
25
  login: 'button[data-testid*=login]',
31
26
  newChat: 'a[href="/"]:has(svg),' // Pencil button (when logged in)
32
27
  + 'button:has([d^="M3.06957"])', // Cycle Arrows button (in temp chat logged out)
33
28
  regen: 'button[data-testid*=regenerate],' // oval button in place of chatbar on errors
34
- // 'Try Again' entry of model selector below msg
35
- + 'div[role=menuitem] div:has(svg):has(path[d^="M3.06957"])',
36
- scroll: 'button:has(> svg > path[d^="M12 21C11.7348"])',
29
+ + 'button:has(use[href$="sprites-core-k5zux585.svg#ec66f0"])', // 'Try again...' button below msg
30
+ scroll: 'button:has(use[href$="sprites-core-k5zux585.svg#ac89a7"])',
37
31
  search: 'button[data-testid=composer-button-search]',
38
- reason: 'button[data-testid=composer-button-reason]',
39
32
  send: 'button[data-testid=send-button]',
40
- sidebar: 'div[style*=-sidebar-width] button[data-testid=close-sidebar-button], div[style*=-sidebar-rail-width] button[aria-controls=stage-slideover-sidebar]',
41
- stop: 'div:has(> svg > path[d^="M10 2.08496C14.3713"])',
42
- upload: 'button:has(> svg > path[d^="M12 3C12.5523"])',
33
+ sidebar: 'div[style*=-sidebar-width] button[data-testid=close-sidebar-button],'
34
+ + 'div[style*=-sidebar-rail-width] button[aria-controls=stage-slideover-sidebar]',
35
+ signup: 'button[data-testid=signup-button]',
36
+ stop: 'button[data-testid=stop-button]',
37
+ upload: 'div[data-testid=composer-action-file-upload],' // tall chatbar
38
+ + 'button#composer-plus-btn', // short chatbar
43
39
  voice: 'button[data-testid*=composer-speech-button]'
44
40
  },
45
41
  chatDivs: {
@@ -338,7 +334,7 @@ const chatgpt = {
338
334
  modalContainer.append(modal) ; document.body.append(modalContainer)
339
335
 
340
336
  // Enqueue alert
341
- let alertQueue = JSON.parse(localStorage.alertQueue)
337
+ let alertQueue = JSON.parse(localStorage.alertQueue ??= JSON.stringify([]))
342
338
  alertQueue.push(modalContainer.id)
343
339
  localStorage.alertQueue = JSON.stringify(alertQueue)
344
340
 
@@ -1383,7 +1379,8 @@ const chatgpt = {
1383
1379
  }
1384
1380
 
1385
1381
  // Enqueue notification
1386
- let notifyProps = JSON.parse(localStorage.notifyProps)
1382
+ let notifyProps = JSON.parse(localStorage.notifyProps
1383
+ ??= JSON.stringify({ queue: { topRight: [], bottomRight: [], bottomLeft: [], topLeft: [] }}))
1387
1384
  notifyProps.queue[notificationDiv.quadrant].push(notificationDiv.id)
1388
1385
  localStorage.notifyProps = JSON.stringify(notifyProps)
1389
1386
 
@@ -1642,10 +1639,10 @@ const chatgpt = {
1642
1639
  textArea.dispatchEvent(new Event('input', { bubbles: true })) // enable send button
1643
1640
  setTimeout(function delaySend() {
1644
1641
  const sendBtn = chatgpt.getSendButton()
1645
- if (!sendBtn?.hasAttribute('disabled')) { // send msg
1642
+ if (!sendBtn?.hasAttribute('disabled')) // send msg
1646
1643
  method.toLowerCase() == 'click' || chatgpt.browser.isMobile() ? sendBtn.click()
1647
1644
  : textArea.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }))
1648
- } else setTimeout(delaySend, 222)
1645
+ else setTimeout(delaySend, 222)
1649
1646
  }, 222)
1650
1647
  },
1651
1648
 
@@ -1839,15 +1836,13 @@ const chatgpt = {
1839
1836
  return console.error(`🤖 chatgpt.js >> Invalid element! Valid elems are [${validElems}]`)
1840
1837
 
1841
1838
  const newElem = document.createElement(elem == 'dropdown' ? 'select' : elem)
1842
- newElem.id = Math.floor(chatgpt.randomFloat() * 1000000) + Date.now() // Add random id to the element
1839
+ newElem.id = Math.floor(chatgpt.randomFloat() * 1000000) + Date.now()
1843
1840
 
1844
1841
  if (elem == 'button') {
1845
- newElem.textContent = attrs?.label && typeof attrs.label == 'string'
1846
- ? attrs.label
1847
- : 'chatgpt.js button'
1842
+ newElem.textContent = attrs?.label && typeof attrs.label == 'string' ? attrs.label : 'chatgpt.js button'
1848
1843
  const icon = document.createElement('img')
1849
- icon.src = attrs?.icon && typeof attrs.icon == 'string' // Can also be base64 encoded image string
1850
- ? attrs.icon // Add icon to button element if given, else default one
1844
+ icon.src = attrs?.icon && typeof attrs.icon == 'string' // can also be base64 encoded image string
1845
+ ? attrs.icon // add icon to button element if given, else default one
1851
1846
  : `${chatgpt.endpoints.assets}/starters/chrome/extension/icons/icon128.png`
1852
1847
  icon.width = 18
1853
1848
  newElem.firstChild.before(icon)
@@ -1855,9 +1850,9 @@ const chatgpt = {
1855
1850
  }
1856
1851
 
1857
1852
  else if (elem == 'dropdown') {
1858
- if (!attrs?.items || // There no are options to add
1853
+ if (!attrs?.items || // there no are options to add
1859
1854
  !Array.isArray(attrs.items) || // It's not an array
1860
- !attrs.items.length) // The array is empty
1855
+ !attrs.items.length) // the array is empty
1861
1856
  attrs.items = [{ text: '🤖 chatgpt.js option', value: 'chatgpt.js option value' }] // Set default dropdown entry
1862
1857
 
1863
1858
  if (!attrs.items.every(el => typeof el == 'object')) // The entries of the array are not objects
@@ -1,10 +1,10 @@
1
1
  /**
2
- * © 2023–2025 KudoAI & contributors under the MIT license.
2
+ * © 2023–2026 KudoAI & contributors under the MIT license.
3
3
  * Source: https://github.com/KudoAI/chatgpt.js
4
4
  * User guide: https://chatgptjs.org/userguide
5
5
  * Latest minified release: https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js/chatgpt.min.js
6
6
  */
7
- localStorage.alertQueue=JSON.stringify([]),localStorage.notifyProps=JSON.stringify({queue:{topRight:[],bottomRight:[],bottomLeft:[],topLeft:[]}});let chatgpt={endpoints:{assets:"https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@3b5663fada6475f268867184bb27ca293387de0c",openAI:{session:"https://chatgpt.com/api/auth/session",chats:"https://chatgpt.com/backend-api/conversations",chat:"https://chatgpt.com/backend-api/conversation",share_create:"https://chatgpt.com/backend-api/share/create",share:"https://chatgpt.com/backend-api/share",instructions:"https://chatgpt.com/backend-api/user_system_messages"}},selectors:{btns:{continue:'button:has(svg[class*=rotate] > path[d^="M4.47189"])',createImage:"button[data-testid=composer-create-image]",deepResearch:"button[data-testid=composer-deep-research]",login:"button[data-testid*=login]",newChat:'a[href="/"]:has(svg),button:has([d^="M3.06957"])',regen:'button[data-testid*=regenerate],div[role=menuitem] div:has(svg):has(path[d^="M3.06957"])',scroll:'button:has(> svg > path[d^="M12 21C11.7348"])',search:"button[data-testid=composer-button-search]",reason:"button[data-testid=composer-button-reason]",send:"button[data-testid=send-button]",sidebar:"div[style*=-sidebar-width] button[data-testid=close-sidebar-button], div[style*=-sidebar-rail-width] button[aria-controls=stage-slideover-sidebar]",stop:'div:has(> svg > path[d^="M10 2.08496C14.3713"])',upload:'button:has(> svg > path[d^="M12 3C12.5523"])',voice:"button[data-testid*=composer-speech-button]"},chatDivs:{convo:"div[class*=thread]",msg:"div[data-message-author-role]",reply:"div[data-message-author-role=assistant]"},chatHistory:"div#history",errors:{toast:"div.toast-root",txt:"div[class*=text-error]"},footer:"div#thread-bottom-container > div:last-of-type > div, span.text-sm.leading-none",header:"header#page-header",links:{newChat:'nav a[href="/"]',sidebarItem:"nav a"},sidebar:"div#stage-slideover-sidebar, div.bg-token-sidebar-surface-primary",ssgManifest:'script[src*="_ssgManifest.js"]'},actAs(s){return new Promise((r,a)=>{let n=new XMLHttpRequest;n.open("GET","https://cdn.jsdelivr.net/gh/KudoAI/chat-prompts@3b5663fada6475f268867184bb27ca293387de0c/dist/personas.min.json",!0),n.send(),n.onload=()=>{if(200!=n.status)return a("🤖 chatgpt.js >> Request failed. Cannot retrieve prompts data.");var e=JSON.parse(n.responseText).personas;if(s){var t=e.find(e=>e.title.toLowerCase()==s.toLowerCase());if(!t)return a(`🤖 chatgpt.js >> Persona '${s}' was not found!`);chatgpt.send(t.prompt,"click"),console.info(`Loading ${s} persona...`),chatgpt.isIdle().then(()=>console.info("Persona activated!"))}else{console.log("\n%c🤖 chatgpt.js personas\n","font-family: sans-serif ; font-size: xxx-large ; font-weight: bold");for(var o of e)console.log("%c"+o.title,"font-family: monospace ; font-size: larger ;")}return r()}})},activateDarkMode(){document.documentElement.classList.replace("light","dark"),document.documentElement.style.colorScheme=localStorage.theme="dark"},activateLightMode(){document.documentElement.classList.replace("dark","light"),document.documentElement.style.colorScheme=localStorage.theme="light"},alert(o,r,e,a,t){let n=chatgpt.isDarkMode()?"dark":"light",s=chatgpt.browser.isMobile(),i={dismiss:{click(e){e.target!=e.currentTarget&&!e.target.closest("[class*=-close-btn]")||f()},key(e){if(/^(?: |Space|Enter|Return|Esc)/.test(e.key)&&[32,13,27].includes(e.keyCode))for(var t of m){var t=document.getElementById(t);if(!t||"none"==t.style.display)return;e.key.startsWith("Esc")||27==e.keyCode?f():(t=t.querySelector(".modal-buttons").lastChild)&&(t.click(),e.preventDefault())}}},drag:{mousedown(e){var t;0==e.button&&/auto|default/.test(getComputedStyle(e.target).cursor)&&(chatgpt.draggingModal=e.currentTarget,e.preventDefault(),Object.assign(chatgpt.draggingModal.style,{transition:"transform 0.1s ease",transform:"scale(1.05)"}),document.body.style.cursor="grabbing",[...chatgpt.draggingModal.children].forEach(e=>e.style.pointerEvents="none"),["mousemove","mouseup"].forEach(e=>document.addEventListener(e,i.drag[e])),t=chatgpt.draggingModal.getBoundingClientRect(),i.drag.offsetX=e.clientX-t.left+21,i.drag.offsetY=e.clientY-t.top+12)},mousemove(e){var t;chatgpt.draggingModal&&(t=e.clientX-i.drag.offsetX,e=e.clientY-i.drag.offsetY,Object.assign(chatgpt.draggingModal.style,{left:t+"px",top:e+"px"}))},mouseup(){Object.assign(chatgpt.draggingModal.style,{cursor:"inherit",transition:"inherit",transform:"scale(1)"}),document.body.style.cursor="",[...chatgpt.draggingModal.children].forEach(e=>e.style.pointerEvents=""),["mousemove","mouseup"].forEach(e=>document.removeEventListener(e,i.drag[e])),chatgpt.draggingModal=null}}},c=document.createElement("div"),l=(c.id=Math.floor(1e6*chatgpt.randomFloat())+Date.now(),c.classList.add("chatgpt-modal"),document.createElement("div")),d=document.createElement("h2"),g=document.createElement("p");var h=1739338889852;let u=document.querySelector("#chatgpt-modal-style"),p=((!u||parseInt(u.getAttribute("last-updated"),10)<h)&&(u||((u=document.createElement("style")).id="chatgpt-modal-style",u.setAttribute("last-updated",h.toString()),document.head.append(u)),u.textContent=`.chatgpt-modal { /* vars */
7
+ let chatgpt={endpoints:{assets:"https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@bcd8cedb8d9ab69b9ec00f7f9e0564c3784c01c7",openAI:{session:"https://chatgpt.com/api/auth/session",chats:"https://chatgpt.com/backend-api/conversations",chat:"https://chatgpt.com/backend-api/conversation",share_create:"https://chatgpt.com/backend-api/share/create",share:"https://chatgpt.com/backend-api/share",instructions:"https://chatgpt.com/backend-api/user_system_messages"}},selectors:{btns:{continue:'button:has(svg[class*=rotate] > path[d^="M4.47189"])',createImage:"button[data-testid=composer-button-create-image]",login:"button[data-testid*=login]",newChat:'a[href="/"]:has(svg),button:has([d^="M3.06957"])',regen:'button[data-testid*=regenerate],button:has(use[href$="sprites-core-k5zux585.svg#ec66f0"])',scroll:'button:has(use[href$="sprites-core-k5zux585.svg#ac89a7"])',search:"button[data-testid=composer-button-search]",send:"button[data-testid=send-button]",sidebar:"div[style*=-sidebar-width] button[data-testid=close-sidebar-button],div[style*=-sidebar-rail-width] button[aria-controls=stage-slideover-sidebar]",signup:"button[data-testid=signup-button]",stop:"button[data-testid=stop-button]",upload:"div[data-testid=composer-action-file-upload],button#composer-plus-btn",voice:"button[data-testid*=composer-speech-button]"},chatDivs:{convo:"div[class*=thread]",msg:"div[data-message-author-role]",reply:"div[data-message-author-role=assistant]"},chatHistory:"div#history",errors:{toast:"div.toast-root",txt:"div[class*=text-error]"},footer:"div#thread-bottom-container > div:last-of-type > div, span.text-sm.leading-none",header:"header#page-header",links:{newChat:'nav a[href="/"]',sidebarItem:"nav a"},sidebar:"div#stage-slideover-sidebar, div.bg-token-sidebar-surface-primary",ssgManifest:'script[src*="_ssgManifest.js"]'},actAs(s){return new Promise((r,a)=>{let n=new XMLHttpRequest;n.open("GET","https://cdn.jsdelivr.net/gh/KudoAI/chat-prompts@bcd8cedb8d9ab69b9ec00f7f9e0564c3784c01c7/dist/personas.min.json",!0),n.send(),n.onload=()=>{if(200!=n.status)return a("🤖 chatgpt.js >> Request failed. Cannot retrieve prompts data.");var e=JSON.parse(n.responseText).personas;if(s){var t=e.find(e=>e.title.toLowerCase()==s.toLowerCase());if(!t)return a(`🤖 chatgpt.js >> Persona '${s}' was not found!`);chatgpt.send(t.prompt,"click"),console.info(`Loading ${s} persona...`),chatgpt.isIdle().then(()=>console.info("Persona activated!"))}else{console.log("\n%c🤖 chatgpt.js personas\n","font-family: sans-serif ; font-size: xxx-large ; font-weight: bold");for(var o of e)console.log("%c"+o.title,"font-family: monospace ; font-size: larger ;")}return r()}})},activateDarkMode(){document.documentElement.classList.replace("light","dark"),document.documentElement.style.colorScheme=localStorage.theme="dark"},activateLightMode(){document.documentElement.classList.replace("dark","light"),document.documentElement.style.colorScheme=localStorage.theme="light"},alert(o,r,e,a,t){let n=chatgpt.isDarkMode()?"dark":"light",s=chatgpt.browser.isMobile(),i={dismiss:{click(e){e.target!=e.currentTarget&&!e.target.closest("[class*=-close-btn]")||f()},key(e){if(/^(?: |Space|Enter|Return|Esc)/.test(e.key)&&[32,13,27].includes(e.keyCode))for(var t of m){var t=document.getElementById(t);if(!t||"none"==t.style.display)return;e.key.startsWith("Esc")||27==e.keyCode?f():(t=t.querySelector(".modal-buttons").lastChild)&&(t.click(),e.preventDefault())}}},drag:{mousedown(e){var t;0==e.button&&/auto|default/.test(getComputedStyle(e.target).cursor)&&(chatgpt.draggingModal=e.currentTarget,e.preventDefault(),Object.assign(chatgpt.draggingModal.style,{transition:"transform 0.1s ease",transform:"scale(1.05)"}),document.body.style.cursor="grabbing",[...chatgpt.draggingModal.children].forEach(e=>e.style.pointerEvents="none"),["mousemove","mouseup"].forEach(e=>document.addEventListener(e,i.drag[e])),t=chatgpt.draggingModal.getBoundingClientRect(),i.drag.offsetX=e.clientX-t.left+21,i.drag.offsetY=e.clientY-t.top+12)},mousemove(e){var t;chatgpt.draggingModal&&(t=e.clientX-i.drag.offsetX,e=e.clientY-i.drag.offsetY,Object.assign(chatgpt.draggingModal.style,{left:t+"px",top:e+"px"}))},mouseup(){Object.assign(chatgpt.draggingModal.style,{cursor:"inherit",transition:"inherit",transform:"scale(1)"}),document.body.style.cursor="",[...chatgpt.draggingModal.children].forEach(e=>e.style.pointerEvents=""),["mousemove","mouseup"].forEach(e=>document.removeEventListener(e,i.drag[e])),chatgpt.draggingModal=null}}},c=document.createElement("div"),l=(c.id=Math.floor(1e6*chatgpt.randomFloat())+Date.now(),c.classList.add("chatgpt-modal"),document.createElement("div")),d=document.createElement("h2"),g=document.createElement("p");var u=1739338889852;let h=document.querySelector("#chatgpt-modal-style"),p=((!h||parseInt(h.getAttribute("last-updated"),10)<u)&&(h||((h=document.createElement("style")).id="chatgpt-modal-style",h.setAttribute("last-updated",u.toString()),document.head.append(h)),h.textContent=`.chatgpt-modal { /* vars */
8
8
  --transition: opacity 0.65s cubic-bezier(.165,.84,.44,1), /* for fade-in */
9
9
  transform 0.55s cubic-bezier(.165,.84,.44,1) ; /* for move-in */
10
10
  --bg-transition: background-color 0.25s ease ; /* for bg dim */
@@ -74,7 +74,7 @@ localStorage.alertQueue=JSON.stringify([]),localStorage.notifyProps=JSON.stringi
74
74
  .chatgpt-modal input[type=checkbox]:focus {
75
75
  outline: none ; box-shadow: none ; -webkit-box-shadow: none ; -moz-box-shadow: none }
76
76
  .chatgpt-modal .checkbox-group label {
77
- cursor: pointer ; font-size: 14px ; color: ${"dark"==n?"#e1e1e1":"#1e1e1e"}}`),d.textContent=o||"",g.innerText=r||"",chatgpt.renderHTML(g),document.createElement("div"));p.classList.add("modal-buttons","no-mobile-tap-outline"),e&&(e=Array.isArray(e)?e:[e]).forEach(e=>{var t=document.createElement("button");t.textContent=e.name.replace(/[_-]\w/g,e=>e.slice(1).toUpperCase()).replace(/([A-Z])/g," $1").replace(/^\w/,e=>e.toUpperCase()),t.onclick=()=>{f(),e()},p.insertBefore(t,p.firstChild)});h=document.createElement("button"),h.textContent=e?"Dismiss":"OK",p.insertBefore(h,p.firstChild),p.lastChild.classList.add("primary-modal-btn"),o=document.createElement("div");if(a){o.classList.add("checkbox-group");let e=a,t=document.createElement("input");t.type="checkbox",t.onchange=e;r=document.createElement("label");r.onclick=()=>{t.checked=!t.checked,e()},r.textContent=e.name[0].toUpperCase()+e.name.slice(1).replace(/([A-Z])/g,(e,t)=>" "+t.toLowerCase()).replace(/\b(\w+)nt\b/gi,"$1n't").trim(),o.append(t),o.append(r)}e=document.createElement("div"),e.title="Close",e.classList.add("modal-close-btn","no-mobile-tap-outline"),a=document.createElementNS("http://www.w3.org/2000/svg","svg"),a.setAttribute("height","10px"),a.setAttribute("viewBox","0 0 14 14"),a.setAttribute("fill","none"),r=document.createElementNS("http://www.w3.org/2000/svg","path");r.setAttribute("fill-rule","evenodd"),r.setAttribute("clip-rule","evenodd"),r.setAttribute("fill",chatgpt.isDarkMode()?"white":"black"),r.setAttribute("d","M13.7071 1.70711C14.0976 1.31658 14.0976 0.683417 13.7071 0.292893C13.3166 -0.0976312 12.6834 -0.0976312 12.2929 0.292893L7 5.58579L1.70711 0.292893C1.31658 -0.0976312 0.683417 -0.0976312 0.292893 0.292893C-0.0976312 0.683417 -0.0976312 1.31658 0.292893 1.70711L5.58579 7L0.292893 12.2929C-0.0976312 12.6834 -0.0976312 13.3166 0.292893 13.7071C0.683417 14.0976 1.31658 14.0976 1.70711 13.7071L7 8.41421L12.2929 13.7071C12.6834 14.0976 13.3166 14.0976 13.7071 13.7071C14.0976 13.3166 14.0976 12.6834 13.7071 12.2929L8.41421 7L13.7071 1.70711Z"),a.append(r),e.append(a),l.append(e,d,g,o,p),l.style.width=`${t||458}px`,c.append(l),document.body.append(c);let m=JSON.parse(localStorage.alertQueue),f=(m.push(c.id),localStorage.alertQueue=JSON.stringify(m),c.style.display="none",1==m.length&&(c.style.display="",setTimeout(()=>{l.parentNode.style.backgroundColor=`rgba(67,70,72,${"dark"==n?.62:.33})`,l.parentNode.classList.add("animated")},100)),[c,e,a,h].forEach(e=>e.onclick=i.dismiss.click),document.addEventListener("keydown",i.dismiss.key),l.onmousedown=i.drag.mousedown,()=>{c.style.backgroundColor="transparent",l.style.animation="alert-zoom-fade-out 0.165s ease-out",l.onanimationend=()=>{if(c.remove(),(m=JSON.parse(localStorage.alertQueue)).shift(),localStorage.alertQueue=JSON.stringify(m),document.removeEventListener("keydown",i.dismiss.key),m.length){let e=document.getElementById(m[0]);setTimeout(()=>{e.style.display="",setTimeout(()=>e.classList.add("animated"),100)},500)}}});return c.id},async askAndGetReply(e){return chatgpt.send(e),await chatgpt.isIdle(),chatgpt.getChatData("active","msg","chatgpt","latest")},autoRefresh:{activate(e){if(this.isActive)return console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Auto refresh already active!`);let o=this,r=(this.toggle.refreshFrame(),t=>{var e=Math.max(2,Math.floor(21*chatgpt.randomFloat()-10));o.isActive=setTimeout(()=>{var e=document.querySelector(chatgpt.selectors.ssgManifest);e&&(document.querySelector("#refresh-frame").src=e.src+"?"+Date.now(),console.log(`↻ ChatGPT >> [${o.nowTimeStamp()}] ChatGPT session refreshed`)),r(t)},1e3*(t+e))});r(e?parseInt(e,10):30),console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Auto refresh activated`),navigator.userAgent.includes("Chrome")&&void 0!==document.hidden&&document.addEventListener("visibilitychange",this.toggle.beacons)},deactivate(){this.isActive?(this.toggle.refreshFrame(),document.removeEventListener("visibilitychange",this.toggle.beacons),clearTimeout(this.isActive),this.isActive=null,console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Auto refresh de-activated`)):console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Auto refresh already inactive!`)},nowTimeStamp(){var e=new Date,t=e.getHours()%12||12;let o=e.getMinutes(),r=e.getSeconds();o<10&&(o="0"+o),r<10&&(r="0"+r);e=e.getHours()<12?"AM":"PM";return`${t}:${o}:${r} `+e},toggle:{beacons(){chatgpt.autoRefresh.beaconID?(clearInterval(chatgpt.autoRefresh.beaconID),chatgpt.autoRefresh.beaconID=null,console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Beacons de-activated`)):(chatgpt.autoRefresh.beaconID=setInterval(()=>{navigator.sendBeacon("https://httpbin.org/post",new Uint8Array),console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Beacon sent`)},9e4),console.log(`ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Beacons activated`))},refreshFrame(){let e=document.querySelector("#refresh-frame");e?e.remove():(e=Object.assign(document.createElement("iframe"),{id:"refresh-frame",style:"display: none"}),document.head.prepend(e))}}},browser:{isLightMode(){return window.matchMedia?.("(prefers-color-scheme: light)")?.matches},isDarkMode(){return window.matchMedia?.("(prefers-color-scheme: dark)")?.matches},isChromium(){return!!JSON.stringify(navigator.userAgentData?.brands)?.includes("Chromium")},isChrome(){return!!JSON.stringify(navigator.userAgentData?.brands)?.includes("Chrome")},isEdge(){return!!JSON.stringify(navigator.userAgentData?.brands)?.includes("Edge")},isBrave(){return!!JSON.stringify(navigator.userAgentData?.brands)?.includes("Brave")},isFirefox(){return navigator.userAgent.includes("Firefox")},isFullScreen(){var e=navigator.userAgent;return e.includes("Chrome")?window.matchMedia("(display-mode: fullscreen)").matches:e.includes("Firefox")?window.fullScreen:/MSIE|rv:/.test(e)?document.msFullscreenElement:document.webkitIsFullScreen},isMobile(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)}},async clearChats(){return new Promise((o,r)=>chatgpt.getAccessToken().then(e=>{let t=new XMLHttpRequest;t.open("PATCH",chatgpt.endpoints.openAI.chats,!0),t.setRequestHeader("Content-Type","application/json"),t.setRequestHeader("Authorization","Bearer "+e),t.onload=()=>{if(200!=t.status)return r("🤖 chatgpt.js >> Request failed. Cannot clear chats.");console.info("Chats successfully cleared"),o()},t.send(JSON.stringify({is_visible:!1}))}).catch(e=>r(new Error(e.message))))},code:{async execute(e){return e?"string"!=typeof e?console.error("Code argument must be a string!"):(chatgpt.send("Display the output as if you were terminal:\n\n"+e),console.info("Executing code..."),await chatgpt.isIdle(),chatgpt.code.extract(await chatgpt.getChatData("active","msg","chatgpt","latest"))):console.error("Code argument not supplied. Pass some code!")},extract(e){var t=e.match(/(?<=```.*\n)[\s\S]*?(?=```)/g);return t?t[t.length-1]:e},async isIdle(t=null){let a={childList:!0,subtree:!0};var e=t?new Promise(e=>setTimeout(()=>e(!1),t)):null,o=(async()=>{await new Promise(o=>{document.querySelector(chatgpt.selectors.chatDivs.msg)?o():new MutationObserver((e,t)=>{document.querySelector(chatgpt.selectors.chatDivs.msg)&&(t.disconnect(),o())}).observe(document.body,a)}),await new Promise(o=>new MutationObserver((e,t)=>{chatgpt.getStopBtn()&&(t.disconnect(),o())}).observe(document.body,{childList:!0,subtree:!0}));let e=document.querySelectorAll(chatgpt.selectors.chatDivs.reply),r=e[e.length-1];return await new Promise(o=>new MutationObserver((e,t)=>{r?.querySelector("pre")&&(t.disconnect(),o())}).observe(document.body,a)),new Promise(o=>new MutationObserver((e,t)=>{!r?.querySelector("pre")?.nextElementSibling&&chatgpt.getStopBtn()||(t.disconnect(),o(!0))}).observe(document.body,a))})();return e?Promise.race([o,e]):o},async minify(e){return e?"string"!=typeof e?console.error("Code argument must be a string!"):(chatgpt.send("Minify the following code:\n\n"+e),console.info("Minifying code..."),await chatgpt.isIdle(),chatgpt.code.extract(await chatgpt.getChatData("active","msg","chatgpt","latest"))):console.error("Code argument not supplied. Pass some code!")},async obfuscate(e){return e?"string"!=typeof e?console.error("Code argument must be a string!"):(chatgpt.send("Obfuscate the following code:\n\n"+e),console.info("Obfuscating code..."),await chatgpt.isIdle(),chatgpt.code.extract(await chatgpt.getChatData("active","msg","chatgpt","latest"))):console.error("Code argument not supplied. Pass some code!")},async refactor(e,t){if(!e)return console.error("Code (1st) argument not supplied. Pass some code!");for(let e=0;e<arguments.length;e++)if("string"!=typeof arguments[e])return console.error(`Argument ${e+1} must be a string.`);return chatgpt.send(`Refactor the following code for ${t||"brevity"}:
77
+ cursor: pointer ; font-size: 14px ; color: ${"dark"==n?"#e1e1e1":"#1e1e1e"}}`),d.textContent=o||"",g.innerText=r||"",chatgpt.renderHTML(g),document.createElement("div"));p.classList.add("modal-buttons","no-mobile-tap-outline"),e&&(e=Array.isArray(e)?e:[e]).forEach(e=>{var t=document.createElement("button");t.textContent=e.name.replace(/[_-]\w/g,e=>e.slice(1).toUpperCase()).replace(/([A-Z])/g," $1").replace(/^\w/,e=>e.toUpperCase()),t.onclick=()=>{f(),e()},p.insertBefore(t,p.firstChild)});u=document.createElement("button"),u.textContent=e?"Dismiss":"OK",p.insertBefore(u,p.firstChild),p.lastChild.classList.add("primary-modal-btn"),o=document.createElement("div");if(a){o.classList.add("checkbox-group");let e=a,t=document.createElement("input");t.type="checkbox",t.onchange=e;r=document.createElement("label");r.onclick=()=>{t.checked=!t.checked,e()},r.textContent=e.name[0].toUpperCase()+e.name.slice(1).replace(/([A-Z])/g,(e,t)=>" "+t.toLowerCase()).replace(/\b(\w+)nt\b/gi,"$1n't").trim(),o.append(t),o.append(r)}e=document.createElement("div"),e.title="Close",e.classList.add("modal-close-btn","no-mobile-tap-outline"),a=document.createElementNS("http://www.w3.org/2000/svg","svg"),a.setAttribute("height","10px"),a.setAttribute("viewBox","0 0 14 14"),a.setAttribute("fill","none"),r=document.createElementNS("http://www.w3.org/2000/svg","path");r.setAttribute("fill-rule","evenodd"),r.setAttribute("clip-rule","evenodd"),r.setAttribute("fill",chatgpt.isDarkMode()?"white":"black"),r.setAttribute("d","M13.7071 1.70711C14.0976 1.31658 14.0976 0.683417 13.7071 0.292893C13.3166 -0.0976312 12.6834 -0.0976312 12.2929 0.292893L7 5.58579L1.70711 0.292893C1.31658 -0.0976312 0.683417 -0.0976312 0.292893 0.292893C-0.0976312 0.683417 -0.0976312 1.31658 0.292893 1.70711L5.58579 7L0.292893 12.2929C-0.0976312 12.6834 -0.0976312 13.3166 0.292893 13.7071C0.683417 14.0976 1.31658 14.0976 1.70711 13.7071L7 8.41421L12.2929 13.7071C12.6834 14.0976 13.3166 14.0976 13.7071 13.7071C14.0976 13.3166 14.0976 12.6834 13.7071 12.2929L8.41421 7L13.7071 1.70711Z"),a.append(r),e.append(a),l.append(e,d,g,o,p),l.style.width=`${t||458}px`,c.append(l),document.body.append(c);let m=JSON.parse(localStorage.alertQueue??=JSON.stringify([])),f=(m.push(c.id),localStorage.alertQueue=JSON.stringify(m),c.style.display="none",1==m.length&&(c.style.display="",setTimeout(()=>{l.parentNode.style.backgroundColor=`rgba(67,70,72,${"dark"==n?.62:.33})`,l.parentNode.classList.add("animated")},100)),[c,e,a,u].forEach(e=>e.onclick=i.dismiss.click),document.addEventListener("keydown",i.dismiss.key),l.onmousedown=i.drag.mousedown,()=>{c.style.backgroundColor="transparent",l.style.animation="alert-zoom-fade-out 0.165s ease-out",l.onanimationend=()=>{if(c.remove(),(m=JSON.parse(localStorage.alertQueue)).shift(),localStorage.alertQueue=JSON.stringify(m),document.removeEventListener("keydown",i.dismiss.key),m.length){let e=document.getElementById(m[0]);setTimeout(()=>{e.style.display="",setTimeout(()=>e.classList.add("animated"),100)},500)}}});return c.id},async askAndGetReply(e){return chatgpt.send(e),await chatgpt.isIdle(),chatgpt.getChatData("active","msg","chatgpt","latest")},autoRefresh:{activate(e){if(this.isActive)return console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Auto refresh already active!`);let o=this,r=(this.toggle.refreshFrame(),t=>{var e=Math.max(2,Math.floor(21*chatgpt.randomFloat()-10));o.isActive=setTimeout(()=>{var e=document.querySelector(chatgpt.selectors.ssgManifest);e&&(document.querySelector("#refresh-frame").src=e.src+"?"+Date.now(),console.log(`↻ ChatGPT >> [${o.nowTimeStamp()}] ChatGPT session refreshed`)),r(t)},1e3*(t+e))});r(e?parseInt(e,10):30),console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Auto refresh activated`),navigator.userAgent.includes("Chrome")&&void 0!==document.hidden&&document.addEventListener("visibilitychange",this.toggle.beacons)},deactivate(){this.isActive?(this.toggle.refreshFrame(),document.removeEventListener("visibilitychange",this.toggle.beacons),clearTimeout(this.isActive),this.isActive=null,console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Auto refresh de-activated`)):console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Auto refresh already inactive!`)},nowTimeStamp(){var e=new Date,t=e.getHours()%12||12;let o=e.getMinutes(),r=e.getSeconds();o<10&&(o="0"+o),r<10&&(r="0"+r);e=e.getHours()<12?"AM":"PM";return`${t}:${o}:${r} `+e},toggle:{beacons(){chatgpt.autoRefresh.beaconID?(clearInterval(chatgpt.autoRefresh.beaconID),chatgpt.autoRefresh.beaconID=null,console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Beacons de-activated`)):(chatgpt.autoRefresh.beaconID=setInterval(()=>{navigator.sendBeacon("https://httpbin.org/post",new Uint8Array),console.log(`↻ ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Beacon sent`)},9e4),console.log(`ChatGPT >> [${chatgpt.autoRefresh.nowTimeStamp()}] Beacons activated`))},refreshFrame(){let e=document.querySelector("#refresh-frame");e?e.remove():(e=Object.assign(document.createElement("iframe"),{id:"refresh-frame",style:"display: none"}),document.head.prepend(e))}}},browser:{isLightMode(){return window.matchMedia?.("(prefers-color-scheme: light)")?.matches},isDarkMode(){return window.matchMedia?.("(prefers-color-scheme: dark)")?.matches},isChromium(){return!!JSON.stringify(navigator.userAgentData?.brands)?.includes("Chromium")},isChrome(){return!!JSON.stringify(navigator.userAgentData?.brands)?.includes("Chrome")},isEdge(){return!!JSON.stringify(navigator.userAgentData?.brands)?.includes("Edge")},isBrave(){return!!JSON.stringify(navigator.userAgentData?.brands)?.includes("Brave")},isFirefox(){return navigator.userAgent.includes("Firefox")},isFullScreen(){var e=navigator.userAgent;return e.includes("Chrome")?window.matchMedia("(display-mode: fullscreen)").matches:e.includes("Firefox")?window.fullScreen:/MSIE|rv:/.test(e)?document.msFullscreenElement:document.webkitIsFullScreen},isMobile(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)}},async clearChats(){return new Promise((o,r)=>chatgpt.getAccessToken().then(e=>{let t=new XMLHttpRequest;t.open("PATCH",chatgpt.endpoints.openAI.chats,!0),t.setRequestHeader("Content-Type","application/json"),t.setRequestHeader("Authorization","Bearer "+e),t.onload=()=>{if(200!=t.status)return r("🤖 chatgpt.js >> Request failed. Cannot clear chats.");console.info("Chats successfully cleared"),o()},t.send(JSON.stringify({is_visible:!1}))}).catch(e=>r(new Error(e.message))))},code:{async execute(e){return e?"string"!=typeof e?console.error("Code argument must be a string!"):(chatgpt.send("Display the output as if you were terminal:\n\n"+e),console.info("Executing code..."),await chatgpt.isIdle(),chatgpt.code.extract(await chatgpt.getChatData("active","msg","chatgpt","latest"))):console.error("Code argument not supplied. Pass some code!")},extract(e){var t=e.match(/(?<=```.*\n)[\s\S]*?(?=```)/g);return t?t[t.length-1]:e},async isIdle(t=null){let a={childList:!0,subtree:!0};var e=t?new Promise(e=>setTimeout(()=>e(!1),t)):null,o=(async()=>{await new Promise(o=>{document.querySelector(chatgpt.selectors.chatDivs.msg)?o():new MutationObserver((e,t)=>{document.querySelector(chatgpt.selectors.chatDivs.msg)&&(t.disconnect(),o())}).observe(document.body,a)}),await new Promise(o=>new MutationObserver((e,t)=>{chatgpt.getStopBtn()&&(t.disconnect(),o())}).observe(document.body,{childList:!0,subtree:!0}));let e=document.querySelectorAll(chatgpt.selectors.chatDivs.reply),r=e[e.length-1];return await new Promise(o=>new MutationObserver((e,t)=>{r?.querySelector("pre")&&(t.disconnect(),o())}).observe(document.body,a)),new Promise(o=>new MutationObserver((e,t)=>{!r?.querySelector("pre")?.nextElementSibling&&chatgpt.getStopBtn()||(t.disconnect(),o(!0))}).observe(document.body,a))})();return e?Promise.race([o,e]):o},async minify(e){return e?"string"!=typeof e?console.error("Code argument must be a string!"):(chatgpt.send("Minify the following code:\n\n"+e),console.info("Minifying code..."),await chatgpt.isIdle(),chatgpt.code.extract(await chatgpt.getChatData("active","msg","chatgpt","latest"))):console.error("Code argument not supplied. Pass some code!")},async obfuscate(e){return e?"string"!=typeof e?console.error("Code argument must be a string!"):(chatgpt.send("Obfuscate the following code:\n\n"+e),console.info("Obfuscating code..."),await chatgpt.isIdle(),chatgpt.code.extract(await chatgpt.getChatData("active","msg","chatgpt","latest"))):console.error("Code argument not supplied. Pass some code!")},async refactor(e,t){if(!e)return console.error("Code (1st) argument not supplied. Pass some code!");for(let e=0;e<arguments.length;e++)if("string"!=typeof arguments[e])return console.error(`Argument ${e+1} must be a string.`);return chatgpt.send(`Refactor the following code for ${t||"brevity"}:
78
78
 
79
79
  `+e),console.info("Refactoring code..."),await chatgpt.isIdle(),chatgpt.code.extract(await chatgpt.getChatData("active","msg","chatgpt","latest"))},async review(e){return e?"string"==typeof e?console.error("Code argument must be a string!"):(chatgpt.send("Review the following code for me:\n\n"+e),console.info("Reviewing code..."),await chatgpt.isIdle(),chatgpt.getChatData("active","msg","chatgpt","latest")):console.error("Code argument not supplied. Pass some code!")},async unminify(e){return e?"string"!=typeof e?console.error("Code argument must be a string!"):(chatgpt.send("Unminify the following code.:\n\n"+e),console.info("Unminifying code..."),await chatgpt.isIdle(),chatgpt.code.extract(await chatgpt.getChatData("active","msg","chatgpt","latest"))):console.error("Code argument not supplied. Pass some code!")},async write(e,t){if(!e)return console.error("Prompt (1st) argument not supplied. Pass a prompt!");if(!t)return console.error("outputLang (2nd) argument not supplied. Pass a language!");for(let e=0;e<arguments.length;e++)if("string"!=typeof arguments[e])return console.error(`Argument ${e+1} must be a string.`);return chatgpt.send(e+`
80
80
 
@@ -85,8 +85,8 @@ Write this as code in `+t),console.info("Writing code..."),await chatgpt.isIdle(
85
85
  CHATGPT: ${l.chatgpt}
86
86
 
87
87
  `}else{s=await(await fetch(await chatgpt.shareChat(e))).text(),i=(new DOMParser).parseFromString(s,"text/html");o=`${i.querySelector("title").textContent||"ChatGPT conversation"}.html`,i.querySelectorAll("link[rel=stylesheet]").forEach(e=>{var t=e.getAttribute("href");t?.startsWith("/")&&e.setAttribute("href","https://chat.openai.com"+t)}),a=(new XMLSerializer).serializeToString(i)}if(console.info(`Exporting transcript as ${t.toUpperCase()}...`),"pdf"==t){a=a.replace(/<svg.*?<\/svg>/g,e=>`<img src="${"data:image/svg+xml,"+encodeURIComponent(e)}">`);let e=window.open("","","toolbar=0, location=0, menubar=0, height=600, width=800");e.document.write(a),setTimeout(()=>{e.print({toPDF:!0})},100)}else{"md"==t&&(c=/<.*<h1(.|\n)*?href=".*?continue[^"]*".*?\/a>.*?<[^/]/.exec(a)[1],a=c||a,o=o.replace(".html",".md"));r=new Blob([a],{type:"text/"+("html"==t?"html":"md"==t?"markdown":"plain")}),n=document.createElement("a"),e=URL.createObjectURL(r);n.href=e,n.download=o,document.body.append(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(e)}},extractCode(){chatgpt.code.extract()},focusChatbar(){chatgpt.getChatBox()?.focus()},footer:{get(){return document.querySelector(chatgpt.selectors.footer)},hide(){var e=chatgpt.footer.get();return e?"hidden"==e.style.visibility?console.info("Footer already hidden!"):void(e.style.display="none"):console.error("Footer element not found!")},show(){var e=chatgpt.footer.get();return e?"hidden"!=e.style.visibility?console.info("Footer already shown!"):void(e.style.display="inherit"):console.error("Footer element not found!")}},generateRandomIP(){var e=Array.from({length:4},()=>Math.floor(256*chatgpt.randomFloat())).join(".");return console.info("IP generated: "+e),e},get(e,t=""){if("string"!=typeof e||"string"!=typeof t)throw new TypeError("Invalid arguments. Both arguments must be strings.");if(!cjsTargetTypes.includes(e.toLowerCase()))throw new Error(`Invalid targetType: ${e}. Valid values are: `+JSON.stringify(cjsTargetTypes));var o,r=[],a=new RegExp(`^get(.*)${e}$`,"i");for(o in chatgpt)"function"==typeof chatgpt[o]&&a.test(o)&&r.push(o.replace(a,"$1").toLowerCase());if(!r.includes(t.toLowerCase()))throw new Error(`Invalid targetName: ${t}. `+(r.length?"Valid values are: "+JSON.stringify(r):"targetType "+e.toLowerCase()+" does not require additional options."));let n=("get"+t+e).toLowerCase();return this[Object.keys(this).find(e=>e.toLowerCase()==n)]()},getAccessToken(){return new Promise((e,t)=>{if(chatgpt.accessToken&&0<=Date.parse(chatgpt.accessToken.expireDate)-Date.parse(new Date))return e(chatgpt.accessToken.token);let o=new XMLHttpRequest;o.open("GET",chatgpt.endpoints.openAI.session,!0),o.setRequestHeader("Content-Type","application/json"),o.onload=()=>{if(200!=o.status)return t("🤖 chatgpt.js >> Request failed. Cannot retrieve access token.");console.info("Token expiration: "+new Date(JSON.parse(o.responseText).expires).toLocaleString().replace(","," at")),chatgpt.accessToken={token:JSON.parse(o.responseText).accessToken,expireDate:JSON.parse(o.responseText).expires},e(chatgpt.accessToken.token)},o.send()})},getAccountDetails(...s){var e,t=["email","id","image","name","picture"];for(e of s=arguments[0]?Array.isArray(arguments[0])?arguments[0]:Array.from(arguments):t)if(!t.includes(e))return console.error(`Invalid detail arg '${e}' supplied. Valid details are:
88
- `+` [${t}]`);return new Promise((r,a)=>{let n=new XMLHttpRequest;n.open("GET",chatgpt.endpoints.openAI.session,!0),n.setRequestHeader("Content-Type","application/json"),n.onload=()=>{if(200!=n.status)return a("🤖 chatgpt.js >> Request failed. Cannot retrieve account details.");var e,t=JSON.parse(n.responseText).user,o={};for(e of s)o[e]=t[e];return r(o)},n.send()})},getChatBox(){return document.getElementById("prompt-textarea")},getChatData(d=1,o="all",u="all",p="all"){var e,t=["all","id","title","create_time","update_time","msg"],r=["all","both","user","chatgpt"];d=d?Number.isInteger(d)||/^\d+$/.test(d)?0==parseInt(d,10)?0:parseInt(d,10)-1:d:"active",o=["all",""].includes(o)?t.filter(e=>/^(?!all$|msg$).*/.test(e)):Array.isArray(o)?o:[o],u=u?r.includes(u)?u:"invalid":"all",p=Number.isInteger(p)||/^\d+$/.test(p)?0==parseInt(p,10)?0:parseInt(p,10)-1:["all","latest"].includes(p.toLowerCase())?p.toLowerCase():p?"invalid":"all";for(e of o)if(!t.includes(e))return console.error(`Invalid detail arg '${e}' passed. Valid details are:
89
- `+` [${t}]`);if("invalid"==u)return console.error("Invalid sender arg passed. Valid senders are:\n"+` [${r}]`);if("invalid"==p)return console.error("Invalid msgToGet arg passed. Valid msg's to get are:\n [ 'all' | 'latest' | index of msg to get ]");let a=(e,c)=>{let l=/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/;return new Promise((t,s)=>{let i=new XMLHttpRequest;i.open("GET",chatgpt.endpoints.openAI.chats,!0),i.setRequestHeader("Content-Type","application/json"),i.setRequestHeader("Authorization","Bearer "+e),i.onload=()=>{if(200!=i.status)return s("🤖 chatgpt.js >> Request failed. Cannot retrieve chat details.");var o=JSON.parse(i.responseText).items;if(o.length<=0)return s("🤖 chatgpt.js >> Chat list is empty.");var r={};if(Number.isInteger(d)||"latest"==d||"active"==d&&!new RegExp(`/${l.source}$`).test(location.href)){if((d=Number.isInteger(d)?d:0)>o.length)return s("🤖 chatgpt.js >> Chat with index "+(d+1)+` is out of bounds. Only ${o.length} chats exist!`);for(var e of c)r[e]=o[d][e]}else{var a,n="active"==d||new RegExp(`^${l.source}$`).test(d)?"id":"title";"active"==d&&(d=l.exec(window.location.href)[0]);let e,t;for(e=0;e<o.length;e++)if(o[e][n]==d){t=!0;break}if(!t)return s(`🤖 chatgpt.js >> No chat with ${n} = ${d} found.`);for(a of c)r[a]=o[e][a]}return t(r)},i.send()})},n=t=>new Promise((d,g)=>{let h=new XMLHttpRequest;a(t,["id"]).then(e=>{h.open("GET",chatgpt.endpoints.openAI.chat+"/"+e.id,!0),h.setRequestHeader("Content-Type","application/json"),h.setRequestHeader("Authorization","Bearer "+t),h.onload=()=>{if(200!=h.status)return g("🤖 chatgpt.js >> Request failed. Cannot retrieve chat messages.");let n=JSON.parse(h.responseText).mapping;var e,t,o=[],r=[],a=[];for(e in n)"user"==n[e]?.message?.author?.role&&o.push({id:n[e].id,msg:n[e].message});if(o.sort((e,t)=>e.msg.create_time-t.msg.create_time),parseInt(p,10)+1>o.length)return g("🤖 chatgpt.js >> Message/response with index "+(p+1)+` is out of bounds. Only ${o.length} messages/responses exist!`);for(t of o){let e=[];for(var s in n)"assistant"==n[s]?.message?.author?.role&&((e,t)=>{let o=e,r=0;for(;o&&r<10;){var a=n[o];if(!a?.message)return;if(a.id==t)return 1;o=a.parent,r++}})(s,t.id)&&e.push(n[s].message);e.sort((e,t)=>e.create_time-t.create_time),e=1==(e=e.map(e=>{switch(e.content.content_type){case"code":return e.content.text;case"text":return e.content.parts[0];default:return}})).length?e[0]:e,r.push(e)}if("user"==u)for(var i in o)a.push(o[i].msg.content.parts[0]);else if("chatgpt"==u)for(var c of r)a.push("latest"==p?r[r.length-1]:c);else{let e=0;for(var l in o)a.push({user:o[l].msg.content.parts[0],chatgpt:"latest"==p?r[e][r[e].length-1]:r[e]}),e++}return d("all"==p?a:"latest"==p?a[a.length-1]:a[p])},h.send()})});return new Promise(t=>chatgpt.getAccessToken().then(e=>t(o.includes("msg")?n(e):a(e,o))))},getChatInput(){return chatgpt.getChatBox().firstChild.innerText},getContinueButton(){return document.querySelector(chatgpt.selectors.btns.continue)},getErrorMsg(){return document.querySelector(chatgpt.selectors.errors.txt+":last-of-type")?.innerText},getFooterDiv(){return chatgpt.footer.get()},getHeaderDiv(){return chatgpt.header.get()},getLastPrompt(){return chatgpt.getChatData("active","msg","user","latest")},getLastResponse(){return chatgpt.getChatData("active","msg","chatgpt","latest")},getLoginButton(){return document.querySelector(chatgpt.selectors.btns.login)},getNewChatButton(){return document.querySelector(chatgpt.selectors.btns.newChat)},getNewChatLink(){return document.querySelector(chatgpt.selectors.links.newChat)},getRegenerateButton(){return document.querySelector(chatgpt.selectors.btns.regen)},getResponse(){return chatgpt.response.get(...arguments)},getResponseFromAPI(e,t){return chatgpt.response.getFromAPI(e,t)},getResponseFromDOM(e){return chatgpt.response.getFromDOM(e)},getScrollToBottomButton(){return document.querySelector(chatgpt.selectors.btns.scroll)},getSendButton(){return document.querySelector(chatgpt.selectors.btns.send)},getStopButton(){return document.querySelector(chatgpt.selectors.btns.stop)},getUserLanguage(){return navigator.languages[0]||navigator.language||navigator.browserLanguage||navigator.systemLanguage||navigator.userLanguage||""},getVoiceButton(){return document.querySelector(chatgpt.selectors.btns.voice)},header:{get(){return document.querySelector(chatgpt.selectors.header)},hide(){chatgpt.header.get().style.display="none"},show(){chatgpt.header.get().style.display="flex"}},hideFooter(){chatgpt.footer.hide()},hideHeader(){chatgpt.header.hide()},history:{async isLoaded(t=null){var e=t?new Promise(e=>setTimeout(()=>e(!1),t)):null,o=new Promise(o=>{document.querySelector(chatgpt.selectors.chatHistory)?o(!0):new MutationObserver((e,t)=>{document.querySelector(chatgpt.selectors.chatHistory)&&(t.disconnect(),o(!0))}).observe(document.documentElement,{childList:!0,subtree:!0})});return e?Promise.race([o,e]):o}},instructions:{add(r,a){var e;return r?"string"!=typeof r?console.error("Instruction must be a string"):(e=["user","chatgpt"],a?"string"!=typeof a?console.error("Target must be a string"):(a=a.toLowerCase(),e.includes(a)?(r=`
88
+ `+` [${t}]`);return new Promise((r,a)=>{let n=new XMLHttpRequest;n.open("GET",chatgpt.endpoints.openAI.session,!0),n.setRequestHeader("Content-Type","application/json"),n.onload=()=>{if(200!=n.status)return a("🤖 chatgpt.js >> Request failed. Cannot retrieve account details.");var e,t=JSON.parse(n.responseText).user,o={};for(e of s)o[e]=t[e];return r(o)},n.send()})},getChatBox(){return document.getElementById("prompt-textarea")},getChatData(d=1,o="all",h="all",p="all"){var e,t=["all","id","title","create_time","update_time","msg"],r=["all","both","user","chatgpt"];d=d?Number.isInteger(d)||/^\d+$/.test(d)?0==parseInt(d,10)?0:parseInt(d,10)-1:d:"active",o=["all",""].includes(o)?t.filter(e=>/^(?!all$|msg$).*/.test(e)):Array.isArray(o)?o:[o],h=h?r.includes(h)?h:"invalid":"all",p=Number.isInteger(p)||/^\d+$/.test(p)?0==parseInt(p,10)?0:parseInt(p,10)-1:["all","latest"].includes(p.toLowerCase())?p.toLowerCase():p?"invalid":"all";for(e of o)if(!t.includes(e))return console.error(`Invalid detail arg '${e}' passed. Valid details are:
89
+ `+` [${t}]`);if("invalid"==h)return console.error("Invalid sender arg passed. Valid senders are:\n"+` [${r}]`);if("invalid"==p)return console.error("Invalid msgToGet arg passed. Valid msg's to get are:\n [ 'all' | 'latest' | index of msg to get ]");let a=(e,c)=>{let l=/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/;return new Promise((t,s)=>{let i=new XMLHttpRequest;i.open("GET",chatgpt.endpoints.openAI.chats,!0),i.setRequestHeader("Content-Type","application/json"),i.setRequestHeader("Authorization","Bearer "+e),i.onload=()=>{if(200!=i.status)return s("🤖 chatgpt.js >> Request failed. Cannot retrieve chat details.");var o=JSON.parse(i.responseText).items;if(o.length<=0)return s("🤖 chatgpt.js >> Chat list is empty.");var r={};if(Number.isInteger(d)||"latest"==d||"active"==d&&!new RegExp(`/${l.source}$`).test(location.href)){if((d=Number.isInteger(d)?d:0)>o.length)return s("🤖 chatgpt.js >> Chat with index "+(d+1)+` is out of bounds. Only ${o.length} chats exist!`);for(var e of c)r[e]=o[d][e]}else{var a,n="active"==d||new RegExp(`^${l.source}$`).test(d)?"id":"title";"active"==d&&(d=l.exec(window.location.href)[0]);let e,t;for(e=0;e<o.length;e++)if(o[e][n]==d){t=!0;break}if(!t)return s(`🤖 chatgpt.js >> No chat with ${n} = ${d} found.`);for(a of c)r[a]=o[e][a]}return t(r)},i.send()})},n=t=>new Promise((d,g)=>{let u=new XMLHttpRequest;a(t,["id"]).then(e=>{u.open("GET",chatgpt.endpoints.openAI.chat+"/"+e.id,!0),u.setRequestHeader("Content-Type","application/json"),u.setRequestHeader("Authorization","Bearer "+t),u.onload=()=>{if(200!=u.status)return g("🤖 chatgpt.js >> Request failed. Cannot retrieve chat messages.");let n=JSON.parse(u.responseText).mapping;var e,t,o=[],r=[],a=[];for(e in n)"user"==n[e]?.message?.author?.role&&o.push({id:n[e].id,msg:n[e].message});if(o.sort((e,t)=>e.msg.create_time-t.msg.create_time),parseInt(p,10)+1>o.length)return g("🤖 chatgpt.js >> Message/response with index "+(p+1)+` is out of bounds. Only ${o.length} messages/responses exist!`);for(t of o){let e=[];for(var s in n)"assistant"==n[s]?.message?.author?.role&&((e,t)=>{let o=e,r=0;for(;o&&r<10;){var a=n[o];if(!a?.message)return;if(a.id==t)return 1;o=a.parent,r++}})(s,t.id)&&e.push(n[s].message);e.sort((e,t)=>e.create_time-t.create_time),e=1==(e=e.map(e=>{switch(e.content.content_type){case"code":return e.content.text;case"text":return e.content.parts[0];default:return}})).length?e[0]:e,r.push(e)}if("user"==h)for(var i in o)a.push(o[i].msg.content.parts[0]);else if("chatgpt"==h)for(var c of r)a.push("latest"==p?r[r.length-1]:c);else{let e=0;for(var l in o)a.push({user:o[l].msg.content.parts[0],chatgpt:"latest"==p?r[e][r[e].length-1]:r[e]}),e++}return d("all"==p?a:"latest"==p?a[a.length-1]:a[p])},u.send()})});return new Promise(t=>chatgpt.getAccessToken().then(e=>t(o.includes("msg")?n(e):a(e,o))))},getChatInput(){return chatgpt.getChatBox().firstChild.innerText},getContinueButton(){return document.querySelector(chatgpt.selectors.btns.continue)},getErrorMsg(){return document.querySelector(chatgpt.selectors.errors.txt+":last-of-type")?.innerText},getFooterDiv(){return chatgpt.footer.get()},getHeaderDiv(){return chatgpt.header.get()},getLastPrompt(){return chatgpt.getChatData("active","msg","user","latest")},getLastResponse(){return chatgpt.getChatData("active","msg","chatgpt","latest")},getLoginButton(){return document.querySelector(chatgpt.selectors.btns.login)},getNewChatButton(){return document.querySelector(chatgpt.selectors.btns.newChat)},getNewChatLink(){return document.querySelector(chatgpt.selectors.links.newChat)},getRegenerateButton(){return document.querySelector(chatgpt.selectors.btns.regen)},getResponse(){return chatgpt.response.get(...arguments)},getResponseFromAPI(e,t){return chatgpt.response.getFromAPI(e,t)},getResponseFromDOM(e){return chatgpt.response.getFromDOM(e)},getScrollToBottomButton(){return document.querySelector(chatgpt.selectors.btns.scroll)},getSendButton(){return document.querySelector(chatgpt.selectors.btns.send)},getStopButton(){return document.querySelector(chatgpt.selectors.btns.stop)},getUserLanguage(){return navigator.languages[0]||navigator.language||navigator.browserLanguage||navigator.systemLanguage||navigator.userLanguage||""},getVoiceButton(){return document.querySelector(chatgpt.selectors.btns.voice)},header:{get(){return document.querySelector(chatgpt.selectors.header)},hide(){chatgpt.header.get().style.display="none"},show(){chatgpt.header.get().style.display="flex"}},hideFooter(){chatgpt.footer.hide()},hideHeader(){chatgpt.header.hide()},history:{async isLoaded(t=null){var e=t?new Promise(e=>setTimeout(()=>e(!1),t)):null,o=new Promise(o=>{document.querySelector(chatgpt.selectors.chatHistory)?o(!0):new MutationObserver((e,t)=>{document.querySelector(chatgpt.selectors.chatHistory)&&(t.disconnect(),o(!0))}).observe(document.documentElement,{childList:!0,subtree:!0})});return e?Promise.race([o,e]):o}},instructions:{add(r,a){var e;return r?"string"!=typeof r?console.error("Instruction must be a string"):(e=["user","chatgpt"],a?"string"!=typeof a?console.error("Target must be a string"):(a=a.toLowerCase(),e.includes(a)?(r=`
90
90
 
91
91
  `+r,new Promise(o=>{chatgpt.getAccessToken().then(async e=>{var t=await this.fetchData();return"user"==a?t.about_user_message+=r:"chatgpt"==a&&(t.about_model_message+=r),await this.sendRequest("POST",e,t),o()})})):console.error(`Invalid target ${a}. Valid targets are [${e}]`)):console.error("Please provide a valid target!")):console.error("Please provide an instruction")},clear(r){var e=["user","chatgpt"];return r?"string"!=typeof r?console.error("Target must be a string"):(r=r.toLowerCase(),e.includes(r)?new Promise(o=>{chatgpt.getAccessToken().then(async e=>{var t=await this.fetchData();return"user"==r?t.about_user_message="":"chatgpt"==r&&(t.about_model_message=""),await this.sendRequest("POST",e,t),o()})}):console.error(`Invalid target ${r}. Valid targets are [${e}]`)):console.error("Please provide a valid target!")},fetchData(){return new Promise(t=>chatgpt.getAccessToken().then(async e=>t(await this.sendRequest("GET",e))))},sendRequest(a,e,n){for(let e=0;e<arguments.length-1;e++)if("string"==typeof arguments[e])return console.error(`Argument ${e+1} must be a string`);var t=["POST","GET"];return(a=(a||"").trim().toUpperCase())&&t.includes(a)?e?n&&"object"!=typeof n?console.error(`Invalid body data type. Got ${typeof n}, expected object`):new Promise((t,o)=>{let r=new XMLHttpRequest;r.open(a,chatgpt.endpoints.openAI.instructions,!0),r.setRequestHeader("Accept-Language","en-US"),r.setRequestHeader("Authorization","Bearer "+e),"POST"==a&&r.setRequestHeader("Content-Type","application/json"),r.onload=()=>{var e=JSON.parse(r.responseText);return 422==r.status?o("🤖 chatgpt.js >> Character limit exceeded. Custom instructions can have a maximum length of 1500 characters."):403==r.status&&"content_policy"==e.detail.reason?o("🤖 chatgpt.js >> "+e.detail.description):200!=r.status?o("🤖 chatgpt.js >> Request failed. Cannot contact custom instructions endpoint."):(console.info("Custom instructions successfully contacted with method "+a),t(e||{}))},r.send(JSON.stringify(n)||"")}):console.error("Please provide a valid access token!"):console.error("Valid methods are "+t)},turnOff(){return new Promise(o=>chatgpt.getAccessToken().then(async e=>{var t=await this.fetchData();return t.enabled=!1,await this.sendRequest("POST",e,t),o()}))},turnOn(){return new Promise(o=>chatgpt.getAccessToken().then(async e=>{var t=await this.fetchData();return t.enabled=!0,await this.sendRequest("POST",e,t),o()}))},toggle(){return new Promise(t=>this.fetchData().then(async e=>(await(e.enabled?this.turnOff():this.turnOn()),t())))}},isDarkMode(){return document.documentElement.classList.contains("dark")},isFullScreen(){return chatgpt.browser.isFullScreen()},async isIdle(t=null){let e={childList:!0,subtree:!0};var o=t?new Promise(e=>setTimeout(()=>e(!1),t)):null,r=(async()=>(await new Promise(o=>{document.querySelector(chatgpt.selectors.chatDivs.msg)?o():new MutationObserver((e,t)=>{document.querySelector(chatgpt.selectors.chatDivs.msg)&&(t.disconnect(),o())}).observe(document.body,e)}),await new Promise(o=>new MutationObserver((e,t)=>{chatgpt.getStopBtn()&&(t.disconnect(),o())}).observe(document.body,e)),new Promise(o=>new MutationObserver((e,t)=>{chatgpt.getStopBtn()||(t.disconnect(),o(!0))}).observe(document.body,e))))();return o?Promise.race([r,o]):r},async isLoaded(t=null){var e=t?new Promise(e=>setTimeout(()=>e(!1),t)):null,o=new Promise(o=>{chatgpt.getNewChatBtn()?o(!0):new MutationObserver((e,t)=>{chatgpt.getNewChatBtn()&&(t.disconnect(),o(!0))}).observe(document.documentElement,{childList:!0,subtree:!0})});return e?Promise.race([o,e]):o},isLightMode(){return document.documentElement.classList.contains("light")},isTempChat(){return"?temporary-chat=true"==location.search},isTyping(){return!!this.getStopButton()},login(){window.location.href="https://chat.openai.com/auth/login"},logout(){window.location.href="https://chat.openai.com/auth/logout"},menu:{elems:[],append(e,t={}){var o=["button","dropdown"];if(!e||"string"!=typeof e)return console.error("🤖 chatgpt.js >> Please supply a valid string element name!");if(e=e.toLowerCase(),!o.includes(e))return console.error(`🤖 chatgpt.js >> Invalid element! Valid elems are [${o}]`);let r=document.createElement("dropdown"==e?"select":"button"==e?"a":e);if(r.id=Math.floor(1e6*chatgpt.randomFloat())+Date.now(),"button"==e){r.textContent=t?.label&&"string"==typeof t.label?t.label:"chatgpt.js button";o=document.createElement("img");o.src=t?.icon&&"string"==typeof t.icon?t.icon:chatgpt.endpoints.assets+"/starters/chrome/extension/icons/icon128.png",o.width=18,r.firstChild.before(o),r.onclick=t?.onclick&&"function"==typeof t.onclick?t.onclick:function(){}}else if("dropdown"==e){if(t?.items&&Array.isArray(t.items)&&t.items.length||(t.items=[{text:"🤖 chatgpt.js option",value:"chatgpt.js option value"}]),!t.items.every(e=>"object"==typeof e))return console.error("'items' must be an array of objects!");r.style="background-color: #000 ; width: 100% ; border: none",t.items.forEach(e=>{var t=document.createElement("option");t.textContent=e?.text,t.value=e?.value,r.add(t)})}let a=()=>{var e,t=document.querySelectorAll("a[role=menuitem]");let o;for(e of t)if("Settings"==e.textContent){o=e.classList;break}let r=t[0].parentNode;chatgpt.menu.elems.forEach(e=>{if(e.setAttribute("class",o),!r.contains(e))try{r.firstChild.before(e)}catch(e){console.error(e)}})};this.elems.push(r);o=document.querySelector("nav button[id*=headless]");return this.addedEvent||(o?.addEventListener("click",()=>setTimeout(a,25)),this.addedEvent=!0),r.id},close(){try{document.querySelector("nav [id*=menu-button][aria-expanded=true]").click()}catch(e){console.error(e.message)}},open(){try{document.querySelector("nav [id*=menu-button][aria-expanded=false]").click()}catch(e){console.error(e.message)}}},minify(){chatgpt.code.minify()},notify(...e){var t=chatgpt.isDarkMode()?"dark":"light";let o,r,a,n,s,i=("object"!=typeof e[0]||Array.isArray(e[0])?[o,r,a,n]=e:{msg:o,position:r,notifDuration:a,shadow:n,toast:s}=e[0],a=a?+a:1.75,document.createElement("div"));i.id=Math.floor(1e6*chatgpt.randomFloat())+Date.now(),i.classList.add("chatgpt-notif"),i.textContent=o,document.body.append(i);var e=document.createElement("div"),c=(e.title="Dismiss",e.classList.add("notif-close-btn","no-mobile-tap-outline"),document.createElementNS("http://www.w3.org/2000/svg","svg")),l=(c.setAttribute("height","8px"),c.setAttribute("viewBox","0 0 14 14"),c.setAttribute("fill","none"),c.style.height=c.style.width="8px",document.createElementNS("http://www.w3.org/2000/svg","path")),l=(l.setAttribute("fill-rule","evenodd"),l.setAttribute("clip-rule","evenodd"),l.setAttribute("fill","white"),l.setAttribute("d","M13.7071 1.70711C14.0976 1.31658 14.0976 0.683417 13.7071 0.292893C13.3166 -0.0976312 12.6834 -0.0976312 12.2929 0.292893L7 5.58579L1.70711 0.292893C1.31658 -0.0976312 0.683417 -0.0976312 0.292893 0.292893C-0.0976312 0.683417 -0.0976312 1.31658 0.292893 1.70711L5.58579 7L0.292893 12.2929C-0.0976312 12.6834 -0.0976312 13.3166 0.292893 13.7071C0.683417 14.0976 1.31658 14.0976 1.70711 13.7071L7 8.41421L12.2929 13.7071C12.6834 14.0976 13.3166 14.0976 13.7071 13.7071C14.0976 13.3166 14.0976 12.6834 13.7071 12.2929L8.41421 7L13.7071 1.70711Z"),c.append(l),e.append(c),i.append(e),i.isTop=!r||!/low|bottom/i.test(r),i.isRight=!r||!/left/i.test(r),i.quadrant=(i.isTop?"top":"bottom")+(i.isRight?"Right":"Left"),1746996635555);let d=document.querySelector("#chatgpt-notif-style"),g=((!d||parseInt(d.getAttribute("last-updated"),10)<l)&&(d||((d=document.createElement("style")).id="chatgpt-notif-style",d.setAttribute("last-updated",l.toString()),document.head.append(d)),d.textContent='.chatgpt-notif {font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC","Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", sans-serif ;.no-mobile-tap-outline { outline: none ; -webkit-tap-highlight-color: transparent }background-color: black ; padding: 10px 13px 10px 18px ;border-radius: 11px ; border: 1px solid #f5f5f7 ;opacity: 0 ; position: fixed ; z-index: 9999 ; font-size: 1.8rem ; color: white ;user-select: none ; -webkit-user-select: none ; -moz-user-select: none ; -o-user-select: none ;-ms-user-select: none ;'+`transform: translateX(${i.isRight?"":"-"}35px) ;`+(n?`--shadow: -8px 13px 25px 0 ${/\b(?:shadow|on)\b/i.test(n)?"gray":n};
92
92
  box-shadow: var(--shadow) ; -webkit-box-shadow: var(--shadow) ; -moz-box-shadow: var(--shadow)`:"")+"}"+`.notif-close-btn {
@@ -96,6 +96,6 @@ CHATGPT: ${l.chatgpt}
96
96
  ${"dark"==t?"border: 2px solid white ;":""}
97
97
  margin-${i.isTop?"top: 42px":"bottom: 105px"};
98
98
  transform: translate(-50%, -50%) scale(0.6) !important }
99
- div.chatgpt-notif > div.notif-close-btn { top: 18px ; right: 7px ; transform: scale(2) }`),JSON.parse(localStorage.notifyProps));g.queue[i.quadrant].push(i.id),localStorage.notifyProps=JSON.stringify(g),i.style.top=i.isTop?23..toString()+"px":"",i.style.bottom=i.isTop?"":23..toString()+"px",i.style.right=i.isRight?27..toString()+"px":"",i.style.left=i.isRight?"":27..toString()+"px";e=g.queue[i.quadrant];if(1<e.length)try{for(var h of e.slice(0,-1)){var u=document.getElementById(h),p=u.style.top?"top":"bottom",m=+parseInt(u.style[p])+5+u.getBoundingClientRect().height;u.style[p]=m+"px"}}catch(e){console.warn("Failed to re-position notification:",e)}setTimeout(()=>{i.style.opacity=chatgpt.isDarkMode()?.8:.67,i.style.transform="translateX(0)",i.style.transition="transform 0.15s ease, opacity 0.15s ease"},10);l=a<.35?0:a-.35,t=()=>{i.style.animation="notif-zoom-fade-out 0.35s ease-out",clearTimeout(f)};let f=setTimeout(t,1e3*l);return c.onclick=t,i.onanimationend=()=>{i.remove(),(g=JSON.parse(localStorage.notifyProps)).queue[i.quadrant].shift(),localStorage.notifyProps=JSON.stringify(g)},i},obfuscate(){chatgpt.code.obfuscate()},printAllFunctions(){let o={cmdPrompt:["#ff00ff","#00ff00"],objName:["#0611e9","#f9ee16"],methodName:["#005aff","#ffa500"],entryType:["#467e06","#b981f9"],srcMethod:["#ff0000","#00ffff"]};Object.keys(o).forEach(e=>{o[e][1]=o[e][1]||"#"+(16777215^Number("0x1"+o[e][0].replace(/^#/,""))).toString(16).substring(1).toUpperCase()});var e=[];for(let t in this)if("function"==typeof this[t]){var r=!Object.keys(this).find(e=>Object.keys(this[e]).includes(this[t].name));e.push([r?"chatgpt":"other",t])}else if("object"==typeof this[t])for(var a in this[t])"function"==typeof this[t][a]&&e.push([t,a]);e.sort((e,t)=>e[0].localeCompare(t[0])||e[1].localeCompare(t[1]));var n=window.matchMedia("(prefers-color-scheme: dark)").matches,s="font-family: monospace ; font-size: larger ;";console.log("\n%c🤖 chatgpt.js methods\n","font-family: sans-serif ; font-size: xxx-large ; font-weight: bold");for(let t of e){var i=/chatgpt|other/.test(t[0]),c="chatgpt"==t[0]?this[t[1]].name:"other"!=t[0]?t[0]+"."+t[1]:Object.keys(this).find(e=>Object.keys(this[e]).includes(this[t[1]].name))+"."+this[t[1]].name,l="AsyncFunction"==this[t[1]]?.constructor.name;console.log("%c>> %c"+(i?"":t[0]+".%c")+t[1]+" - https://chatgptjs.org/userguide/"+/(?:.*\.)?(.*)/.exec(c)[1].toLowerCase()+(l?"-async":"")+"\n%c[%c"+("chatgpt"==t[0]&&t[1]==this[t[1]].name||!i?"Function":"Alias of")+"%c: %c"+c+"%c]",s+"font-weight: bold ; color:"+o.cmdPrompt[+n],s+"font-weight: bold ;color:"+o[i?"methodName":"objName"][+n],s+"font-weight: "+(i?"initial":"bold")+";color:"+(i?"initial":o.methodName[+n]),s+"font-weight: "+(i?"bold":"initial")+";color:"+(i?o.entryType[+n]:"initial"),s+"font-weight: "+(i?"initial":"bold")+";color:"+(i?"initial":o.entryType[+n]),s+(i?"font-style: italic":"font-weight: initial")+";color:"+(i?o.srcMethod[+n]:"initial"),s+(i?"font-weight: initial":"font-style: italic")+";color:"+(i?"initial":o.srcMethod[+n]),i?"":s+"color: initial ; font-weight: initial")}},randomFloat(){return(window.crypto||window.msCrypto)?.getRandomValues(new Uint32Array(1))[0]/4294967295||Math.random()},refactor(){chatgpt.code.refactor()},regenerate(){chatgpt.response.regenerate()},renderHTML(s){var i,e=/<([a-z\d]+)\b([^>]*)>([\s\S]*?)<\/\1>/g,c=/(\S+)=['"]?((?:.(?!['"]?\s+\S+=|[>']))+.)['"]?/g,t=s.childNodes;chatgpt.renderHTML.preWrapSet||(s.style.whiteSpace="pre-wrap",chatgpt.renderHTML.preWrapSet=!0,setTimeout(()=>chatgpt.renderHTML.preWrapSet=!1,100));for(i of t)if(i.nodeType==Node.TEXT_NODE){var l=i.nodeValue,d=[...l.matchAll(e)];if(d.length){let e=d[0],[t,o,r,a]=e.slice(0,4),n=document.createElement(o);n.textContent=a;[...r.matchAll(c)].forEach(e=>{var t=e[1],e=e[2].replace(/['"]/g,"");n.setAttribute(t,e)});var d=chatgpt.renderHTML(n),g=document.createTextNode(l.substring(0,e.index)),l=document.createTextNode(l.substring(e.index+t.length));s.replaceChild(g,i),s.insertBefore(d,g.nextSibling),s.insertBefore(l,d.nextSibling)}}else i.nodeType==Node.ELEMENT_NODE&&chatgpt.renderHTML(i);return s},async resend(){chatgpt.send(await chatgpt.getChatData("latest","msg","user","latest"))},response:{continue(){try{chatgpt.getContinueBtn().click()}catch(e){console.error(e.message)}},get(){return this["getFrom"+(location.href.startsWith("https://chatgpt.com/c/")?"DOM":"API")].apply(null,arguments)},getFromAPI(e,t){return e=e||"latest",t=t||"latest",chatgpt.getChatData(e,"msg","chatgpt",t)},getFromDOM(e){var t=document.querySelectorAll("div[data-message-author-role=assistant]"),o=e.toString().toLowerCase();let r="";return t.length?r=(r=(/last|final/.test(o)?t[t.length-1]:t[(Number.isInteger(e)?e:/^\d+/.test(o)?/^\d+/.exec(o)[0]:(/^(?:1|one|fir)(?:st)?$/.test(o)?1:/^(?:2|tw(?:o|en|el(?:ve|f))|seco)(?:nd|t[yi])?(?:e?th)?$/.test(o)?2:/^(?:3|th(?:ree|ir?))(?:rd|teen|t[yi])?(?:e?th)?$/.test(o)?3:/^(?:4|fou?r)(?:teen|t[yi])?(?:e?th)?$/.test(o)?4:/^(?:5|fi(?:ve|f))(?:teen|t[yi])?(?:e?th)?$/.test(o)?5:/^(?:6|six)(?:teen|t[yi])?(?:e?th)?$/.test(o)?6:/^(?:7|seven)(?:teen|t[yi])?(?:e?th)?$/.test(o)?7:/^(?:8|eight?)(?:teen|t[yi])?(?:e?th)?$/.test(o)?8:/^(?:9|nine?)(?:teen|t[yi])?(?:e?th)?$/.test(o)?9:/^(?:10|ten)(?:th)?$/.test(o)?10:1)*(/(?:ty|ieth)$/.test(o)?10:1)+(/teen(?:th)?$/.test(o)?10:0))-1]).textContent).replace(/^ChatGPT(?:ChatGPT)?/,""):console.error("No conversation found!")},getLast(){return chatgpt.getChatData("active","msg","chatgpt","latest")},regenerate(){try{chatgpt.getRegenerateBtn().click()}catch(e){console.error(e.message)}},stopGenerating(){try{chatgpt.getStopBtn().click()}catch(e){console.error(e.message)}}},reviewCode(){chatgpt.code.review()},scrollToBottom(){try{chatgpt.getScrollBtn().click()}catch(e){console.error(e.message)}},send(e,o=""){for(let e=0;e<arguments.length;e++)if("string"!=typeof arguments[e])return console.error(`Argument ${e+1} must be a string!`);let r=chatgpt.getChatBox();if(!r)return console.error("Chatbar element not found!");var t=document.createElement("p");t.textContent=e,r.querySelector("p").replaceWith(t),r.dispatchEvent(new Event("input",{bubbles:!0})),setTimeout(function e(){var t=chatgpt.getSendButton();t?.hasAttribute("disabled")?setTimeout(e,222):"click"==o.toLowerCase()||chatgpt.browser.isMobile()?t.click():r.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter",bubbles:!0}))},222)},sendInNewChat(e){if("string"!=typeof e)return console.error("Message must be a string!");try{chatgpt.getNewChatBtn().click()}catch(e){return console.error(e.message)}setTimeout(()=>chatgpt.send(e),500)},settings:{scheme:{isDark(){return document.documentElement.classList.contains("dark")},isLight(){return document.documentElement.classList.contains("light")},set(e){var t=["dark","light","system"];if(!e)return console.error("Please specify a scheme value!");if(!t.includes(e))return console.error(`Invalid scheme value. Valid values are [${t}]`);let o=e;"system"==e&&(o=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"),localStorage.setItem("theme",e),console.info(`Scheme set to ${e.toUpperCase()}.`),document.documentElement.classList.contains(o)||this.toggle()},toggle(){var[e,t]=this.isDark()?["dark","light"]:["light","dark"];document.documentElement.classList.replace(e,t),document.documentElement.style.colorScheme=t,localStorage.setItem("theme",t)}}},async sentiment(e,t){for(let e=0;e<arguments.length;e++)if("string"!=typeof arguments[e])return console.error(`Argument ${e+1} must be a string.`);return chatgpt.send("What is the sentiment of the following text"+(t?` towards the entity ${t},`:"")+" from strongly negative to strongly positive?\n\n"+e),console.info("Analyzing sentiment..."),await chatgpt.isIdle(),chatgpt.getChatData("active","msg","chatgpt","latest")},setScheme(e){chatgpt.settings.scheme.set(e)},shareChat(s,i="clipboard"){var e=["alert","notify","notification","clipboard","copy"];if(!e.includes(i))return console.error(`Invalid method '${i}' passed. Valid methods are [${e}].`);return new Promise(o=>{chatgpt.getAccessToken().then(t=>{var a;a=t,new Promise((t,o)=>{let r=new XMLHttpRequest;chatgpt.getChatData(s).then(e=>{r.open("GET",chatgpt.endpoints.openAI.chat+"/"+e.id,!0),r.setRequestHeader("Content-Type","application/json"),r.setRequestHeader("Authorization","Bearer "+a),r.onload=()=>200!=r.status?o("🤖 chatgpt.js >> Request failed. Cannot retrieve chat node."):t(JSON.parse(r.responseText).current_node),r.send()})}).then(e=>{var a,n;a=t,n=e,new Promise((t,o)=>{let r=new XMLHttpRequest;chatgpt.getChatData(s).then(e=>{r.open("POST",chatgpt.endpoints.openAI.share_create,!0),r.setRequestHeader("Content-Type","application/json"),r.setRequestHeader("Authorization","Bearer "+a),r.onload=()=>200!=r.status?o("🤖 chatgpt.js >> Request failed. Cannot initialize share chat."):t(JSON.parse(r.responseText)),r.send(JSON.stringify({current_node_id:n,conversation_id:e.id,is_anonymous:!0}))})}).then(e=>{var r,a;r=t,a=e,new Promise((e,t)=>{let o=new XMLHttpRequest;o.open("PATCH",chatgpt.endpoints.openAI.share+"/"+a.share_id,!0),o.setRequestHeader("Content-Type","application/json"),o.setRequestHeader("Authorization","Bearer "+r),o.onload=()=>200!=o.status?t("🤖 chatgpt.js >> Request failed. Cannot share chat."):(console.info(`Chat shared at '${a.share_url}'`),e()),o.send(JSON.stringify({share_id:a.share_id,highlighted_message_id:a.highlighted_message_id,title:a.title,is_public:!0,is_visible:a.is_visible,is_anonymous:a.is_anonymous}))}).then(()=>{["copy","clipboard"].includes(i)?navigator.clipboard.writeText(e.share_url):chatgpt.alert("🚀 Share link created!",`"${e.title}" is available at: <a target="blank" rel="noopener" href="${e.share_url}">${e.share_url}</a>`,[function(){window.open(e.share_url,"_blank","noopener")},function(){navigator.clipboard.writeText(e.share_url)}]),o(e.share_url)})})})})})},showFooter(){chatgpt.footer.show()},showHeader(){chatgpt.header.show()},sidebar:{elems:[],observer:{},activateObserver(){if(this.observer instanceof MutationObserver&&this.observer.disconnect(),!this.elems.length)return console.error("🤖 chatgpt.js >> No elems to append!");let t;for(var e of document.querySelectorAll(chatgpt.selectors.links.sidebarItem))if(/.*chat/.exec(e.text)[0]){t=e.classList,e.parentNode.style.margin="2px 0";break}this.elems.forEach(e=>{e.setAttribute("class",t),e.style.maxHeight=e.style.minHeight="44px",e.style.margin="2px 0"});let o=document.querySelector(chatgpt.selectors.chatHistory);if(!o)return console.error("Sidebar element not found!");this.observer=new MutationObserver(e=>e.forEach(e=>{("childList"==e.type&&e.addedNodes.length||"attributes"==e.type&&"data-chatgptjs"==e.attributeName)&&this.elems.forEach(e=>{if(!o.contains(e))try{o.querySelector("a").parentNode.before(e)}catch(e){console.error(e)}})})),this.observer.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0})},append(e,t={}){var o=["button","dropdown"];if(!e||"string"!=typeof e)return console.error("🤖 chatgpt.js >> Please supply a valid string element name!");if(e=e.toLowerCase(),!o.includes(e))return console.error(`🤖 chatgpt.js >> Invalid element! Valid elems are [${o}]`);let r=document.createElement("dropdown"==e?"select":e);if(r.id=Math.floor(1e6*chatgpt.randomFloat())+Date.now(),"button"==e){r.textContent=t?.label&&"string"==typeof t.label?t.label:"chatgpt.js button";o=document.createElement("img");o.src=t?.icon&&"string"==typeof t.icon?t.icon:chatgpt.endpoints.assets+"/starters/chrome/extension/icons/icon128.png",o.width=18,r.firstChild.before(o),r.onclick=t?.onclick&&"function"==typeof t.onclick?t.onclick:function(){}}else if("dropdown"==e){if(t?.items&&Array.isArray(t.items)&&t.items.length||(t.items=[{text:"🤖 chatgpt.js option",value:"chatgpt.js option value"}]),!t.items.every(e=>"object"==typeof e))return console.error("'items' must be an array of objects!");t.items.forEach(e=>{var t=document.createElement("option");t.textContent=e?.text,t.value=e?.value,r.add(t)})}return"dropdown"==e&&(r.style.backgroundColor="var(--gray-900, rgb(32,33,35))"),this.elems.push(r),this.activateObserver(),document.body.setAttribute("data-chatgptjs","observer-trigger"),r.id},exists(){return!!chatgpt.getNewChatLink()},hide(){this.isOn()?this.toggle():console.info("Sidebar already hidden!")},show(){this.isOff()?this.toggle():console.info("Sidebar already shown!")},isOff(){return!this.isOn()},isOn(){var e=chatgpt.sidebar.exists()?document.querySelector(chatgpt.selectors.sidebar):null;return e?chatgpt.browser.isMobile()?"hidden"==document.documentElement.style.overflow:"hidden"!=e.style.visibility&&150<parseInt(getComputedStyle(e).width):console.error("Sidebar element not found!")||!1},toggle(){var e=document.querySelector(chatgpt.selectors.btns.sidebar);e||console.error("Sidebar toggle not found!"),e.click()},async isLoaded(t=5e3){await chatgpt.isLoaded();var e=new Promise(e=>setTimeout(()=>e(!1),t)),o=new Promise(o=>{chatgpt.getNewChatLink()?o(!0):new MutationObserver((e,t)=>{chatgpt.getNewChatLink()&&(t.disconnect(),o(!0))}).observe(document.documentElement,{childList:!0,subtree:!0})});return Promise.race([o,e])}},startNewChat(){try{chatgpt.getNewChatBtn().click()}catch(e){console.error(e.message)}},stop(){chatgpt.response.stopGenerating()},async suggest(e,t){if(!e)return console.error("ideaType (1st argument) not supplied(e.g. 'gifts', 'names', 'recipes', etc.)");for(let e=0;e<arguments.length;e++)if("string"!=typeof arguments[e])return console.error(`Argument ${e+1} must be a string.`);return chatgpt.send("Suggest some names. "+(t||"")),console.info(`Creating ${e}...`),await chatgpt.isIdle(),chatgpt.getChatData("active","msg","chatgpt","latest")},speak(e,{voice:t=2,pitch:o=2,speed:r=1.1,onend:a}={}){if("string"!=typeof e)return console.error("Message must be a string!");var n,s=["voice","pitch","speed","onend"];for(n in arguments[1]){if(!s.includes(n))return console.error(`Invalid option '${n}'. Valid keys are: `+s);var i=arguments[1][n];if("onend"!=n&&"number"!=typeof i&&!/^\d+$/.test(i))return console.error(`Invalid ${n} value '${i}'. Must be a number!`);if("onend"==n&&"function"!=typeof i)return console.error(`Invalid ${n} value. Must be a function!`)}try{var c=new SpeechSynthesisUtterance,l=speechSynthesis.getVoices();Object.assign(c,{text:e,voice:l[t],pitch:o,speed:r,onend:a}),speechSynthesis.speak(c)}catch(e){console.error(e)}},async summarize(e){return e?"string"!=typeof e?console.error("Text argument must be a string!"):(chatgpt.send("Summarize the following text:\n\n"+e),console.info("Summarizing text..."),await chatgpt.isIdle(),chatgpt.getChatData("active","msg","chatgpt","latest")):console.error("Text (1st) argument not supplied. Pass some text!")},toggleScheme(){chatgpt.settings.scheme.toggle()},async translate(e,t){if(!e)return console.error("Text (1st) argument not supplied. Pass some text!");if(!t)return console.error("outputLang (2nd) argument not supplied. Pass a language!");for(let e=0;e<arguments.length;e++)if("string"!=typeof arguments[e])return console.error(`Argument ${e+1} must be a string!`);return chatgpt.send(`Translate the following text to ${t}. Only reply with the translation.
99
+ div.chatgpt-notif > div.notif-close-btn { top: 18px ; right: 7px ; transform: scale(2) }`),JSON.parse(localStorage.notifyProps??=JSON.stringify({queue:{topRight:[],bottomRight:[],bottomLeft:[],topLeft:[]}})));g.queue[i.quadrant].push(i.id),localStorage.notifyProps=JSON.stringify(g),i.style.top=i.isTop?23..toString()+"px":"",i.style.bottom=i.isTop?"":23..toString()+"px",i.style.right=i.isRight?27..toString()+"px":"",i.style.left=i.isRight?"":27..toString()+"px";e=g.queue[i.quadrant];if(1<e.length)try{for(var u of e.slice(0,-1)){var h=document.getElementById(u),p=h.style.top?"top":"bottom",m=+parseInt(h.style[p])+5+h.getBoundingClientRect().height;h.style[p]=m+"px"}}catch(e){console.warn("Failed to re-position notification:",e)}setTimeout(()=>{i.style.opacity=chatgpt.isDarkMode()?.8:.67,i.style.transform="translateX(0)",i.style.transition="transform 0.15s ease, opacity 0.15s ease"},10);l=a<.35?0:a-.35,t=()=>{i.style.animation="notif-zoom-fade-out 0.35s ease-out",clearTimeout(f)};let f=setTimeout(t,1e3*l);return c.onclick=t,i.onanimationend=()=>{i.remove(),(g=JSON.parse(localStorage.notifyProps)).queue[i.quadrant].shift(),localStorage.notifyProps=JSON.stringify(g)},i},obfuscate(){chatgpt.code.obfuscate()},printAllFunctions(){let o={cmdPrompt:["#ff00ff","#00ff00"],objName:["#0611e9","#f9ee16"],methodName:["#005aff","#ffa500"],entryType:["#467e06","#b981f9"],srcMethod:["#ff0000","#00ffff"]};Object.keys(o).forEach(e=>{o[e][1]=o[e][1]||"#"+(16777215^Number("0x1"+o[e][0].replace(/^#/,""))).toString(16).substring(1).toUpperCase()});var e=[];for(let t in this)if("function"==typeof this[t]){var r=!Object.keys(this).find(e=>Object.keys(this[e]).includes(this[t].name));e.push([r?"chatgpt":"other",t])}else if("object"==typeof this[t])for(var a in this[t])"function"==typeof this[t][a]&&e.push([t,a]);e.sort((e,t)=>e[0].localeCompare(t[0])||e[1].localeCompare(t[1]));var n=window.matchMedia("(prefers-color-scheme: dark)").matches,s="font-family: monospace ; font-size: larger ;";console.log("\n%c🤖 chatgpt.js methods\n","font-family: sans-serif ; font-size: xxx-large ; font-weight: bold");for(let t of e){var i=/chatgpt|other/.test(t[0]),c="chatgpt"==t[0]?this[t[1]].name:"other"!=t[0]?t[0]+"."+t[1]:Object.keys(this).find(e=>Object.keys(this[e]).includes(this[t[1]].name))+"."+this[t[1]].name,l="AsyncFunction"==this[t[1]]?.constructor.name;console.log("%c>> %c"+(i?"":t[0]+".%c")+t[1]+" - https://chatgptjs.org/userguide/"+/(?:.*\.)?(.*)/.exec(c)[1].toLowerCase()+(l?"-async":"")+"\n%c[%c"+("chatgpt"==t[0]&&t[1]==this[t[1]].name||!i?"Function":"Alias of")+"%c: %c"+c+"%c]",s+"font-weight: bold ; color:"+o.cmdPrompt[+n],s+"font-weight: bold ;color:"+o[i?"methodName":"objName"][+n],s+"font-weight: "+(i?"initial":"bold")+";color:"+(i?"initial":o.methodName[+n]),s+"font-weight: "+(i?"bold":"initial")+";color:"+(i?o.entryType[+n]:"initial"),s+"font-weight: "+(i?"initial":"bold")+";color:"+(i?"initial":o.entryType[+n]),s+(i?"font-style: italic":"font-weight: initial")+";color:"+(i?o.srcMethod[+n]:"initial"),s+(i?"font-weight: initial":"font-style: italic")+";color:"+(i?"initial":o.srcMethod[+n]),i?"":s+"color: initial ; font-weight: initial")}},randomFloat(){return(window.crypto||window.msCrypto)?.getRandomValues(new Uint32Array(1))[0]/4294967295||Math.random()},refactor(){chatgpt.code.refactor()},regenerate(){chatgpt.response.regenerate()},renderHTML(s){var i,e=/<([a-z\d]+)\b([^>]*)>([\s\S]*?)<\/\1>/g,c=/(\S+)=['"]?((?:.(?!['"]?\s+\S+=|[>']))+.)['"]?/g,t=s.childNodes;chatgpt.renderHTML.preWrapSet||(s.style.whiteSpace="pre-wrap",chatgpt.renderHTML.preWrapSet=!0,setTimeout(()=>chatgpt.renderHTML.preWrapSet=!1,100));for(i of t)if(i.nodeType==Node.TEXT_NODE){var l=i.nodeValue,d=[...l.matchAll(e)];if(d.length){let e=d[0],[t,o,r,a]=e.slice(0,4),n=document.createElement(o);n.textContent=a;[...r.matchAll(c)].forEach(e=>{var t=e[1],e=e[2].replace(/['"]/g,"");n.setAttribute(t,e)});var d=chatgpt.renderHTML(n),g=document.createTextNode(l.substring(0,e.index)),l=document.createTextNode(l.substring(e.index+t.length));s.replaceChild(g,i),s.insertBefore(d,g.nextSibling),s.insertBefore(l,d.nextSibling)}}else i.nodeType==Node.ELEMENT_NODE&&chatgpt.renderHTML(i);return s},async resend(){chatgpt.send(await chatgpt.getChatData("latest","msg","user","latest"))},response:{continue(){try{chatgpt.getContinueBtn().click()}catch(e){console.error(e.message)}},get(){return this["getFrom"+(location.href.startsWith("https://chatgpt.com/c/")?"DOM":"API")].apply(null,arguments)},getFromAPI(e,t){return e=e||"latest",t=t||"latest",chatgpt.getChatData(e,"msg","chatgpt",t)},getFromDOM(e){var t=document.querySelectorAll("div[data-message-author-role=assistant]"),o=e.toString().toLowerCase();let r="";return t.length?r=(r=(/last|final/.test(o)?t[t.length-1]:t[(Number.isInteger(e)?e:/^\d+/.test(o)?/^\d+/.exec(o)[0]:(/^(?:1|one|fir)(?:st)?$/.test(o)?1:/^(?:2|tw(?:o|en|el(?:ve|f))|seco)(?:nd|t[yi])?(?:e?th)?$/.test(o)?2:/^(?:3|th(?:ree|ir?))(?:rd|teen|t[yi])?(?:e?th)?$/.test(o)?3:/^(?:4|fou?r)(?:teen|t[yi])?(?:e?th)?$/.test(o)?4:/^(?:5|fi(?:ve|f))(?:teen|t[yi])?(?:e?th)?$/.test(o)?5:/^(?:6|six)(?:teen|t[yi])?(?:e?th)?$/.test(o)?6:/^(?:7|seven)(?:teen|t[yi])?(?:e?th)?$/.test(o)?7:/^(?:8|eight?)(?:teen|t[yi])?(?:e?th)?$/.test(o)?8:/^(?:9|nine?)(?:teen|t[yi])?(?:e?th)?$/.test(o)?9:/^(?:10|ten)(?:th)?$/.test(o)?10:1)*(/(?:ty|ieth)$/.test(o)?10:1)+(/teen(?:th)?$/.test(o)?10:0))-1]).textContent).replace(/^ChatGPT(?:ChatGPT)?/,""):console.error("No conversation found!")},getLast(){return chatgpt.getChatData("active","msg","chatgpt","latest")},regenerate(){try{chatgpt.getRegenerateBtn().click()}catch(e){console.error(e.message)}},stopGenerating(){try{chatgpt.getStopBtn().click()}catch(e){console.error(e.message)}}},reviewCode(){chatgpt.code.review()},scrollToBottom(){try{chatgpt.getScrollBtn().click()}catch(e){console.error(e.message)}},send(e,o=""){for(let e=0;e<arguments.length;e++)if("string"!=typeof arguments[e])return console.error(`Argument ${e+1} must be a string!`);let r=chatgpt.getChatBox();if(!r)return console.error("Chatbar element not found!");var t=document.createElement("p");t.textContent=e,r.querySelector("p").replaceWith(t),r.dispatchEvent(new Event("input",{bubbles:!0})),setTimeout(function e(){var t=chatgpt.getSendButton();t?.hasAttribute("disabled")?setTimeout(e,222):"click"==o.toLowerCase()||chatgpt.browser.isMobile()?t.click():r.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter",bubbles:!0}))},222)},sendInNewChat(e){if("string"!=typeof e)return console.error("Message must be a string!");try{chatgpt.getNewChatBtn().click()}catch(e){return console.error(e.message)}setTimeout(()=>chatgpt.send(e),500)},settings:{scheme:{isDark(){return document.documentElement.classList.contains("dark")},isLight(){return document.documentElement.classList.contains("light")},set(e){var t=["dark","light","system"];if(!e)return console.error("Please specify a scheme value!");if(!t.includes(e))return console.error(`Invalid scheme value. Valid values are [${t}]`);let o=e;"system"==e&&(o=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"),localStorage.setItem("theme",e),console.info(`Scheme set to ${e.toUpperCase()}.`),document.documentElement.classList.contains(o)||this.toggle()},toggle(){var[e,t]=this.isDark()?["dark","light"]:["light","dark"];document.documentElement.classList.replace(e,t),document.documentElement.style.colorScheme=t,localStorage.setItem("theme",t)}}},async sentiment(e,t){for(let e=0;e<arguments.length;e++)if("string"!=typeof arguments[e])return console.error(`Argument ${e+1} must be a string.`);return chatgpt.send("What is the sentiment of the following text"+(t?` towards the entity ${t},`:"")+" from strongly negative to strongly positive?\n\n"+e),console.info("Analyzing sentiment..."),await chatgpt.isIdle(),chatgpt.getChatData("active","msg","chatgpt","latest")},setScheme(e){chatgpt.settings.scheme.set(e)},shareChat(s,i="clipboard"){var e=["alert","notify","notification","clipboard","copy"];if(!e.includes(i))return console.error(`Invalid method '${i}' passed. Valid methods are [${e}].`);return new Promise(o=>{chatgpt.getAccessToken().then(t=>{var a;a=t,new Promise((t,o)=>{let r=new XMLHttpRequest;chatgpt.getChatData(s).then(e=>{r.open("GET",chatgpt.endpoints.openAI.chat+"/"+e.id,!0),r.setRequestHeader("Content-Type","application/json"),r.setRequestHeader("Authorization","Bearer "+a),r.onload=()=>200!=r.status?o("🤖 chatgpt.js >> Request failed. Cannot retrieve chat node."):t(JSON.parse(r.responseText).current_node),r.send()})}).then(e=>{var a,n;a=t,n=e,new Promise((t,o)=>{let r=new XMLHttpRequest;chatgpt.getChatData(s).then(e=>{r.open("POST",chatgpt.endpoints.openAI.share_create,!0),r.setRequestHeader("Content-Type","application/json"),r.setRequestHeader("Authorization","Bearer "+a),r.onload=()=>200!=r.status?o("🤖 chatgpt.js >> Request failed. Cannot initialize share chat."):t(JSON.parse(r.responseText)),r.send(JSON.stringify({current_node_id:n,conversation_id:e.id,is_anonymous:!0}))})}).then(e=>{var r,a;r=t,a=e,new Promise((e,t)=>{let o=new XMLHttpRequest;o.open("PATCH",chatgpt.endpoints.openAI.share+"/"+a.share_id,!0),o.setRequestHeader("Content-Type","application/json"),o.setRequestHeader("Authorization","Bearer "+r),o.onload=()=>200!=o.status?t("🤖 chatgpt.js >> Request failed. Cannot share chat."):(console.info(`Chat shared at '${a.share_url}'`),e()),o.send(JSON.stringify({share_id:a.share_id,highlighted_message_id:a.highlighted_message_id,title:a.title,is_public:!0,is_visible:a.is_visible,is_anonymous:a.is_anonymous}))}).then(()=>{["copy","clipboard"].includes(i)?navigator.clipboard.writeText(e.share_url):chatgpt.alert("🚀 Share link created!",`"${e.title}" is available at: <a target="blank" rel="noopener" href="${e.share_url}">${e.share_url}</a>`,[function(){window.open(e.share_url,"_blank","noopener")},function(){navigator.clipboard.writeText(e.share_url)}]),o(e.share_url)})})})})})},showFooter(){chatgpt.footer.show()},showHeader(){chatgpt.header.show()},sidebar:{elems:[],observer:{},activateObserver(){if(this.observer instanceof MutationObserver&&this.observer.disconnect(),!this.elems.length)return console.error("🤖 chatgpt.js >> No elems to append!");let t;for(var e of document.querySelectorAll(chatgpt.selectors.links.sidebarItem))if(/.*chat/.exec(e.text)[0]){t=e.classList,e.parentNode.style.margin="2px 0";break}this.elems.forEach(e=>{e.setAttribute("class",t),e.style.maxHeight=e.style.minHeight="44px",e.style.margin="2px 0"});let o=document.querySelector(chatgpt.selectors.chatHistory);if(!o)return console.error("Sidebar element not found!");this.observer=new MutationObserver(e=>e.forEach(e=>{("childList"==e.type&&e.addedNodes.length||"attributes"==e.type&&"data-chatgptjs"==e.attributeName)&&this.elems.forEach(e=>{if(!o.contains(e))try{o.querySelector("a").parentNode.before(e)}catch(e){console.error(e)}})})),this.observer.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0})},append(e,t={}){var o=["button","dropdown"];if(!e||"string"!=typeof e)return console.error("🤖 chatgpt.js >> Please supply a valid string element name!");if(e=e.toLowerCase(),!o.includes(e))return console.error(`🤖 chatgpt.js >> Invalid element! Valid elems are [${o}]`);let r=document.createElement("dropdown"==e?"select":e);if(r.id=Math.floor(1e6*chatgpt.randomFloat())+Date.now(),"button"==e){r.textContent=t?.label&&"string"==typeof t.label?t.label:"chatgpt.js button";o=document.createElement("img");o.src=t?.icon&&"string"==typeof t.icon?t.icon:chatgpt.endpoints.assets+"/starters/chrome/extension/icons/icon128.png",o.width=18,r.firstChild.before(o),r.onclick=t?.onclick&&"function"==typeof t.onclick?t.onclick:function(){}}else if("dropdown"==e){if(t?.items&&Array.isArray(t.items)&&t.items.length||(t.items=[{text:"🤖 chatgpt.js option",value:"chatgpt.js option value"}]),!t.items.every(e=>"object"==typeof e))return console.error("'items' must be an array of objects!");t.items.forEach(e=>{var t=document.createElement("option");t.textContent=e?.text,t.value=e?.value,r.add(t)})}return"dropdown"==e&&(r.style.backgroundColor="var(--gray-900, rgb(32,33,35))"),this.elems.push(r),this.activateObserver(),document.body.setAttribute("data-chatgptjs","observer-trigger"),r.id},exists(){return!!chatgpt.getNewChatLink()},hide(){this.isOn()?this.toggle():console.info("Sidebar already hidden!")},show(){this.isOff()?this.toggle():console.info("Sidebar already shown!")},isOff(){return!this.isOn()},isOn(){var e=chatgpt.sidebar.exists()?document.querySelector(chatgpt.selectors.sidebar):null;return e?chatgpt.browser.isMobile()?"hidden"==document.documentElement.style.overflow:"hidden"!=e.style.visibility&&150<parseInt(getComputedStyle(e).width):console.error("Sidebar element not found!")||!1},toggle(){var e=document.querySelector(chatgpt.selectors.btns.sidebar);e||console.error("Sidebar toggle not found!"),e.click()},async isLoaded(t=5e3){await chatgpt.isLoaded();var e=new Promise(e=>setTimeout(()=>e(!1),t)),o=new Promise(o=>{chatgpt.getNewChatLink()?o(!0):new MutationObserver((e,t)=>{chatgpt.getNewChatLink()&&(t.disconnect(),o(!0))}).observe(document.documentElement,{childList:!0,subtree:!0})});return Promise.race([o,e])}},startNewChat(){try{chatgpt.getNewChatBtn().click()}catch(e){console.error(e.message)}},stop(){chatgpt.response.stopGenerating()},async suggest(e,t){if(!e)return console.error("ideaType (1st argument) not supplied(e.g. 'gifts', 'names', 'recipes', etc.)");for(let e=0;e<arguments.length;e++)if("string"!=typeof arguments[e])return console.error(`Argument ${e+1} must be a string.`);return chatgpt.send("Suggest some names. "+(t||"")),console.info(`Creating ${e}...`),await chatgpt.isIdle(),chatgpt.getChatData("active","msg","chatgpt","latest")},speak(e,{voice:t=2,pitch:o=2,speed:r=1.1,onend:a}={}){if("string"!=typeof e)return console.error("Message must be a string!");var n,s=["voice","pitch","speed","onend"];for(n in arguments[1]){if(!s.includes(n))return console.error(`Invalid option '${n}'. Valid keys are: `+s);var i=arguments[1][n];if("onend"!=n&&"number"!=typeof i&&!/^\d+$/.test(i))return console.error(`Invalid ${n} value '${i}'. Must be a number!`);if("onend"==n&&"function"!=typeof i)return console.error(`Invalid ${n} value. Must be a function!`)}try{var c=new SpeechSynthesisUtterance,l=speechSynthesis.getVoices();Object.assign(c,{text:e,voice:l[t],pitch:o,speed:r,onend:a}),speechSynthesis.speak(c)}catch(e){console.error(e)}},async summarize(e){return e?"string"!=typeof e?console.error("Text argument must be a string!"):(chatgpt.send("Summarize the following text:\n\n"+e),console.info("Summarizing text..."),await chatgpt.isIdle(),chatgpt.getChatData("active","msg","chatgpt","latest")):console.error("Text (1st) argument not supplied. Pass some text!")},toggleScheme(){chatgpt.settings.scheme.toggle()},async translate(e,t){if(!e)return console.error("Text (1st) argument not supplied. Pass some text!");if(!t)return console.error("outputLang (2nd) argument not supplied. Pass a language!");for(let e=0;e<arguments.length;e++)if("string"!=typeof arguments[e])return console.error(`Argument ${e+1} must be a string!`);return chatgpt.send(`Translate the following text to ${t}. Only reply with the translation.
100
100
 
101
101
  `+e),console.info("Translating text..."),await chatgpt.isIdle(),chatgpt.getChatData("active","msg","chatgpt","latest")},unminify(){chatgpt.code.unminify()},uuidv4(){try{return crypto.randomUUID()}catch(e){let o=(new Date).getTime();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{var t=(o+window.crypto.getRandomValues(new Uint32Array(1))[0]/(Math.pow(2,32)-1)*16)%16|0;return o=Math.floor(o/16),("x"==e?t:3&t|8).toString(16)})}},writeCode(){chatgpt.code.write()}},cjsBtnActions=(chatgpt.scheme={...chatgpt.settings.scheme},["click","get"]),cjsTargetTypes=["button","link","div","response"];for(let t of cjsBtnActions)chatgpt[t+"Button"]=function(o){var e=/^[.#]/.test(o)?document.querySelector(o):/send/i.test(o)?document.querySelector(chatgpt.selectors.btns.send):/scroll/i.test(o)?document.querySelector(chatgpt.selectors.btns.scroll):(()=>{for(var e of document.querySelectorAll("button"))if(e.textContent.toLowerCase().includes(o.toLowerCase()))return e;for(var t of document.querySelectorAll(chatgpt.selectors.links.sidebarItem))if(t.textContent.toLowerCase().includes(o.toLowerCase()))return t})();if("click"!=t)return e;e.click()};let cjsFuncAliases=[["actAs","act","become","persona","premadePrompt","preMadePrompt","prePrompt","rolePlay","rp"],["activateAutoRefresh","activateAutoRefresher","activateRefresher","activateSessionRefresher","autoRefresh","autoRefresher","autoRefreshSession","refresher","sessionRefresher"],["continue","continueChat","continueGenerating","continueResponse"],["deactivateAutoRefresh","deactivateAutoRefresher","deactivateRefresher","deactivateSessionRefresher"],["detectLanguage","getLanguage"],["executeCode","codeExecute"],["exists","isAvailable","isExistent","isPresent"],["exportChat","chatExport","export"],["getFooterDiv","getFooter"],["getHeaderDiv","getHeader"],["getLastPrompt","getLastQuery","getMyLastMessage","getMyLastQuery"],["getContinueButton","getContinueGeneratingButton"],["getScrollToBottomButton","getScrollButton"],["getStopButton","getStopGeneratingButton"],["getTextarea","getTextArea","getChatbar","getChatBar","getChatbox","getChatBox"],["getVoiceButton","getVoiceModeButton"],["isFullScreen","isFullscreen"],["isTempChat","isIncognito","isIncognitoMode","isTempChatMode"],["minify","codeMinify","minifyCode"],["new","newChat","startNewChat"],["obfuscate","codeObfuscate","obfuscateCode"],["printAllFunctions","showAllFunctions"],["refactor","codeRefactor","refactorCode"],["refreshReply","regenerate","regenerateReply"],["refreshSession","sessionRefresh"],["renderHTML","renderHtml","renderLinks","renderTags"],["reviewCode","codeReview"],["send","sendChat","sendMessage"],["sendInNewChat","sendNewChat"],["sentiment","analyzeSentiment","sentimentAnalysis"],["startNewChat","new","newChat"],["stop","stopChat","stopGenerating","stopResponse"],["suggest","suggestion","recommend"],["toggleAutoRefresh","toggleAutoRefresher","toggleRefresher","toggleSessionRefresher"],["toggleScheme","toggleMode"],["translate","translation","translator"],["unminify","unminifyCode","codeUnminify"],["writeCode","codeWrite"]],cjsFuncSynonyms=[["account","acct"],["activate","turnOn"],["analyze","check","evaluate","review"],["ask","send","submit"],["button","btn"],["continue","resume"],["chats","history"],["chat","conversation","convo"],["clear","delete","remove"],["data","details"],["deactivate","deActivate","turnOff"],["execute","interpret","interpreter","run"],["firefox","ff"],["generating","generation"],["login","logIn","logOn","signIn","signOn"],["logout","logOut","logOff","signOff","signOut"],["message","msg"],["minify","uglify"],["refactor","rewrite"],["regenerate","regen"],["render","parse"],["reply","response"],["sentiment","attitude","emotion","feeling","opinion","perception"],["speak","play","say","speech","talk","tts"],["summarize","tldr"],["temp","temporary"],["typing","generating"],["unminify","beautify","prettify","prettyPrint"]];function toCamelCase(e){return e.map((e,t)=>0==t?e:e[0].toUpperCase()+e.slice(1)).join("")}!function e(n=chatgpt){for(var t in n)Object.prototype.hasOwnProperty.call(n,t)&&"object"==typeof n[t]&&e(n[t]);let s;do{s=!1;for(let a in n)if(Object.prototype.hasOwnProperty.call(n,a)&&"function"==typeof n[a]){n[a.toLowerCase()]=n[a],cjsFuncAliases.forEach(e=>{e.includes(a)&&e.forEach(e=>{n[e]||(n[e]=n[e.toLowerCase()]=n[a],s=!0)})});let r=a.split(/(?=[A-Z])/);r.forEach(o=>{cjsFuncSynonyms.filter(e=>e.includes(o.toLowerCase())).flat().filter(e=>e!=o.toLowerCase()).forEach(t=>{var e=toCamelCase(r.map(e=>e==o?t:e));n[e]||(n[e]=n[e.toLowerCase()]=n[a],s=!0)})})}}while(s)}();let consolePrefix="🤖 chatgpt.js >> ",ogError=console.error,ogInfo=console.info;console.error=(...e)=>{"string"==typeof e[0]?e[0].startsWith(consolePrefix)?ogError(...e):ogError(consolePrefix+e[0],...e.slice(1)):ogError(consolePrefix,...e)},console.info=e=>{e.startsWith(consolePrefix)?ogInfo(e):ogInfo(consolePrefix+e)};try{window.chatgpt=chatgpt}catch(e){}try{module.exports=chatgpt}catch(e){}
package/docs/README.md CHANGED
@@ -45,29 +45,25 @@
45
45
 
46
46
  <div id="shields" align="center">
47
47
 
48
- <a href="https://github.com/KudoAI/chatgpt.js/stargazers" target="_blank" rel="noopener">
49
- <img src="https://img.shields.io/github/stars/KudoAI/chatgpt.js?label=Stars&color=af68ff&logo=github&logoColor=white&labelColor=464646&style=for-the-badge"></a>
50
48
  <a href="https://github.com/KudoAI/chatgpt.js/blob/main/LICENSE.md" target="_blank" rel="noopener">
51
- <img src="https://img.shields.io/badge/License-MIT-fc4f2d.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
49
+ <img src="https://img.shields.io/badge/License-MIT-orange.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
52
50
  <a href="https://www.npmjs.com/package/@kudoai/chatgpt.js/v/latest" target="_blank" rel="noopener">
53
51
  <img src="https://img.shields.io/npm/v/%40kudoai%2Fchatgpt.js?logo=npm&logoColor=white&labelColor=464646&color=blue&style=for-the-badge&label=Latest+Release"></a>
54
- <a href="https://github.com/KudoAI/chatgpt.js/tree/v3.8.5/dist/chatgpt.min.js" target="_blank" rel="noopener">
55
- <img src="https://img.shields.io/github/size/KudoAI/chatgpt.js/dist/chatgpt.min.js?branch=v3.8.5&label=Minified%20Size&logo=databricks&logoColor=white&labelColor=464646&color=ff69b4&style=for-the-badge"></a>
52
+ <a href="https://github.com/KudoAI/chatgpt.js/tree/v3.9.0/dist/chatgpt.min.js" target="_blank" rel="noopener">
53
+ <img src="https://img.shields.io/github/size/KudoAI/chatgpt.js/dist/chatgpt.min.js?branch=v3.9.0&label=Minified%20Size&logo=databricks&logoColor=white&labelColor=464646&color=ff69b4&style=for-the-badge"></a>
56
54
  <a href="https://www.codefactor.io/repository/github/kudoai/chatgpt.js" target="_blank" rel="noopener">
57
55
  <img src="https://img.shields.io/codefactor/grade/github/kudoai/chatgpt.js?label=Code+Quality&logo=codefactor&logoColor=white&labelColor=464646&color=1acc6c&style=for-the-badge"></a>
58
56
  <a href="https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=kudoai_chatgpt.js" target="_blank" rel="noopener">
59
57
  <img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fsonarcloud.io%2Fapi%2Fmeasures%2Fcomponent%3Fcomponent%3Dkudoai_chatgpt.js%26metricKeys%3Dvulnerabilities&query=%24.component.measures.0.value&style=for-the-badge&logo=sonarcloud&logoColor=white&labelColor=464646&label=Vulnerabilities&color=gold"></a>
60
58
  <a href="https://github.com/sindresorhus/awesome-chatgpt#javascript" target="_blank" rel="noopener">
61
- <img src="https://img.shields.io/badge/Mentioned_in-Awesome-cca8c4?logo=awesomelists&logoColor=white&labelColor=464646&style=for-the-badge"></a>
62
- <a href="https://www.producthunt.com/posts/chatgpt-js" target="_blank" rel="noopener">
63
- <img src="https://img.shields.io/badge/Featured_on-Product_Hunt-ff6154?logo=producthunt&logoColor=white&labelColor=464646&style=for-the-badge"></a>
64
- <a href="https://trendshift.io/repositories/2896" target="_blank" rel="noopener">
65
- <img src="https://img.shields.io/badge/Trended-Top_20_Repository-869da0?logo=github&logoColor=white&labelColor=464646&style=for-the-badge"></a>
59
+ <img src="https://img.shields.io/badge/Mentioned_in-Awesome-af68ff?logo=awesomelists&logoColor=white&labelColor=464646&style=for-the-badge"></a>
66
60
  <a href="#">
67
61
  <img src="https://img.shields.io/badge/jsDelivr_Requests-2,000,000+-2bbbd8.svg?logo=jsdelivr&logoColor=white&labelColor=464646&style=for-the-badge"></a>
68
62
 
69
63
  </div>
70
64
 
65
+ <br><br>
66
+
71
67
  <img height=8px width="100%" src="https://assets.chatgptjs.org/images/separators/gradient-aqua.png?v=e638eac">
72
68
 
73
69
  <div id="intro">
@@ -118,7 +114,7 @@
118
114
 
119
115
  ```js
120
116
  (async () => {
121
- await import('https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.5/dist/chatgpt.min.js');
117
+ await import('https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.9.0/dist/chatgpt.min.js');
122
118
  // Your code here...
123
119
  })();
124
120
  ```
@@ -127,7 +123,7 @@
127
123
 
128
124
  ```js
129
125
  var xhr = new XMLHttpRequest();
130
- xhr.open('GET', 'https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.5/dist/chatgpt.min.js');
126
+ xhr.open('GET', 'https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.9.0/dist/chatgpt.min.js');
131
127
  xhr.onload = function () {
132
128
  if (xhr.status === 200) {
133
129
  var chatgptJS = document.createElement('script');
@@ -150,7 +146,7 @@ function yourCode() {
150
146
 
151
147
  ```js
152
148
  ...
153
- // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.5/dist/chatgpt.min.js
149
+ // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.9.0/dist/chatgpt.min.js
154
150
  // ==/UserScript==
155
151
 
156
152
  // Your code here...
@@ -220,7 +216,7 @@ chatgpt.get('reply', 'last');
220
216
 
221
217
  Each call equally fetches the last response. If you think it works, it probably will... so just type it!
222
218
 
223
- If it didn't, check out the extended [userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.8.5/docs/USERGUIDE.md), or simply submit an [issue](https://github.com/KudoAI/chatgpt.js/issues) or [PR](https://github.com/KudoAI/chatgpt.js/pulls) and it will be integrated, ezpz!
219
+ If it didn't, check out the extended [userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.9.0/docs/USERGUIDE.md), or simply submit an [issue](https://github.com/KudoAI/chatgpt.js/issues) or [PR](https://github.com/KudoAI/chatgpt.js/pulls) and it will be integrated, ezpz!
224
220
 
225
221
  <img height=8px width="100%" src="https://assets.chatgptjs.org/images/separators/gradient-aqua.png?v=e638eac">
226
222
 
@@ -482,7 +478,7 @@ This library exists thanks to code, translations, issues & ideas from the follow
482
478
  <div align="center">
483
479
 
484
480
  **[Releases](https://github.com/KudoAI/chatgpt.js/releases)** /
485
- [Userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.8.5/docs/USERGUIDE.md) /
481
+ [Userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.9.0/docs/USERGUIDE.md) /
486
482
  [Discuss](https://github.com/KudoAI/chatgpt.js/discussions) /
487
483
  [Back to top ↑](#top)
488
484
 
package/docs/USERGUIDE.md CHANGED
@@ -165,7 +165,7 @@
165
165
 
166
166
  ```js
167
167
  (async () => {
168
- await import('https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.5/dist/chatgpt.min.js');
168
+ await import('https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.9.0/dist/chatgpt.min.js');
169
169
  // Your code here...
170
170
  })();
171
171
  ```
@@ -174,7 +174,7 @@
174
174
 
175
175
  ```js
176
176
  var xhr = new XMLHttpRequest();
177
- xhr.open('GET', 'https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.5/dist/chatgpt.min.js');
177
+ xhr.open('GET', 'https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.9.0/dist/chatgpt.min.js');
178
178
  xhr.onload = function () {
179
179
  if (xhr.status === 200) {
180
180
  var chatgptJS = document.createElement('script');
@@ -196,7 +196,7 @@ function yourCode() {
196
196
 
197
197
  ```js
198
198
  ...
199
- // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.5/dist/chatgpt.min.js
199
+ // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.9.0/dist/chatgpt.min.js
200
200
  // ==/UserScript==
201
201
 
202
202
  // Your code here...
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kudoai/chatgpt.js",
3
- "version": "3.8.5",
3
+ "version": "3.9.0",
4
4
  "description": "Client-side JavaScript library for ChatGPT",
5
5
  "author": {
6
6
  "name": "KudoAI & contributors",
@@ -36,8 +36,8 @@
36
36
  "lint:fix-all": "eslint . --fix",
37
37
  "translate": "py utils/translate-en-messages.py",
38
38
  "build:js": "bash utils/build.sh",
39
- "build:js-docs": "minify-js docs --no-mangle",
40
- "build:docs-js": "minify-js docs --no-mangle",
39
+ "build:js-docs": "minify-js docs/assets/js/src docs/assets/js/min --no-mangle",
40
+ "build:docs-js": "npm run build:js-docs",
41
41
  "build:css": "scss-to-css . dist",
42
42
  "preview:docs": "node utils/preview-docs",
43
43
  "bump:patch": "bash utils/bump.sh patch",
@@ -73,19 +73,18 @@
73
73
  ],
74
74
  "bugs": "https://github.com/KudoAI/chatgpt.js/issues",
75
75
  "devDependencies": {
76
- "@adamlui/minify.js": "^1.8.6",
77
- "@adamlui/scss-to-css": "^1.11.1",
76
+ "@adamlui/minify.js": "^2.1.2",
77
+ "@adamlui/scss-to-css": "^2.0.0",
78
78
  "@eslint/css": "^0.14.1",
79
79
  "@eslint/json": "^0.14.0",
80
80
  "@eslint/markdown": "^7.5.1",
81
- "@html-eslint/eslint-plugin": "^0.52.1",
82
- "@html-eslint/parser": "^0.52.0",
83
- "@stylistic/eslint-plugin": "^5.6.1",
81
+ "@html-eslint/eslint-plugin": "^0.54.0",
82
+ "@html-eslint/parser": "^0.54.0",
83
+ "@stylistic/eslint-plugin": "^5.7.1",
84
84
  "docsify-cli": "^5.0.0-rc.3",
85
85
  "eslint": "^9.39.2",
86
86
  "eslint-plugin-import": "^2.32.0",
87
- "eslint-plugin-regexp": "^2.10.0",
88
- "eslint-plugin-yml": "^1.19.1",
87
+ "eslint-plugin-regexp": "^3.0.0",
89
88
  "get-port": "^7.1.0",
90
89
  "husky": "^9.1.7"
91
90
  }
@@ -22,7 +22,7 @@
22
22
 
23
23
  # 🏛️ MIT License
24
24
 
25
- **Copyright © 2023–2025 [KudoAI](https://github.com/KudoAI) & contributors**
25
+ **Copyright © 2023–2026 [KudoAI](https://github.com/KudoAI) & contributors**
26
26
 
27
27
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
28
28
 
@@ -1,4 +1,4 @@
1
- // Requires lib/<chatgpt|dom>.js + app + env
1
+ // Requires lib/<chatgpt|css|dom>.js + app + env
2
2
 
3
3
  window.modals = {
4
4
 
@@ -76,7 +76,7 @@ window.modals = {
76
76
  if (!modal) return // to support non-div this.open()s
77
77
  if (!this.styles) this.stylize() // to init/append stylesheet
78
78
  modal.classList.add(this.class) ; modal.parentNode.classList.add(`${this.class}-bg`)
79
- dom.addRisingParticles(modal)
79
+ css.addRisingParticles(modal)
80
80
  },
81
81
 
82
82
  observeRemoval(modal, modalType) { // to maintain stack for proper nav
@@ -1,11 +1,12 @@
1
1
  // NOTE: This script relies on the powerful chatgpt.js library @ https://chatgpt.js.org
2
- // © 2023–2025 KudoAI & contributors under the MIT license
2
+ // © 2023–2026 KudoAI & contributors under the MIT license
3
3
 
4
4
  (async () => {
5
5
 
6
6
  // Import JS resources
7
7
  for (const resource of [
8
- 'components/modals.js', 'lib/chatgpt.js', 'lib/dom.js', 'lib/feedback.js', 'lib/settings.js', 'lib/ui.js'
8
+ 'components/modals.js', 'lib/chatgpt.js', 'lib/css.min.js', 'lib/dom.min.js', 'lib/feedback.js',
9
+ 'lib/settings.js', 'lib/ui.js'
9
10
  ]) await import(chrome.runtime.getURL(resource))
10
11
 
11
12
  // Init ENV context
@@ -21,7 +22,7 @@
21
22
  alert: () => modals.alert(...['title', 'msg', 'btns', 'checkbox', 'width'].map(arg => options[arg])),
22
23
  showAbout: () => {
23
24
  if (!source?.endsWith('service-worker.js')) return
24
- config.skipAlert = true
25
+ app.config.skipAlert = true
25
26
  chatgpt.isLoaded().then(() => modals.open('about'))
26
27
  },
27
28
  syncConfigToUI: () => syncConfigToUI(options)
@@ -30,20 +31,20 @@
30
31
 
31
32
  // Init SETTINGS
32
33
  await settings.load(Object.keys(settings.controls))
33
- if (!config.skipAlert) await settings.load('skipAlert') // only if not showing About modal
34
+ if (!app.config.skipAlert) await settings.load('skipAlert') // only if not showing About modal
34
35
 
35
36
  // Define FUNCTIONS
36
37
 
37
38
  async function syncConfigToUI(options = {}) { // eslint-disable-line
38
- await settings.load('extensionDisabled', Object.keys(settings.controls)) // load from Chrome storage to content.js config
39
- if (config.extensionDisabled) {
39
+ await settings.load('extensionDisabled', Object.keys(settings.controls)) // load from Chrome storage to app.config
40
+ if (app.config.extensionDisabled) {
40
41
  // Remove all hacks
41
42
  } else {
42
43
  // Add/remove hacks to reflect each potentially updated setting per settings.controls in lib/settings.mjs
43
44
  // e.g. if you created toolbar popup toggle to hide ChatGPT footer using hiddenFooter key...
44
- // ...here you would use options.updatedKey == 'hiddenFooter' && config.hiddenFooter...
45
+ // ...here you would use options.updatedKey == 'hiddenFooter' && app.config.hiddenFooter...
45
46
  // ...to conditionally append/remove hidden footer style...
46
- // ...(initial style creation + append if config.hiddenFooter would go in main routine)
47
+ // ...(initial style creation + append if app.config.hiddenFooter would go in main routine)
47
48
  }
48
49
  }
49
50
 
@@ -62,15 +63,15 @@
62
63
  color}.min.css`
63
64
  })))
64
65
 
65
- if (config.extensionDisabled) return
66
+ if (app.config.extensionDisabled) return
66
67
 
67
- if (!config.skipAlert) // alert to extension load
68
+ if (!app.config.skipAlert) // alert to extension load
68
69
  modals.alert('≫ ChatGPT extension loaded! 🚀', // title
69
70
  'Success! Press Ctrl+Shift+J to view all chatgpt.js methods.', // msg
70
71
  function getHelp() { // button
71
72
  open(`${app.urls.github}/issues`) },
72
73
  function dontShowAgain() { // checkbox
73
- settings.save('skipAlert', !config.skipAlert) }
74
+ settings.save('skipAlert', !app.config.skipAlert) }
74
75
  )
75
76
 
76
77
  // Monitor SCHEME PREF CHANGES to update modal colors + env.ui.scheme for your use
@@ -1,12 +1,8 @@
1
- // © 2023–2025 KudoAI & contributors under the MIT license.
1
+ // © 2023–2026 KudoAI & contributors under the MIT license.
2
2
  // Source: https://github.com/KudoAI/chatgpt.js
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 feedback props
7
- localStorage.alertQueue = JSON.stringify([])
8
- localStorage.notifyProps = JSON.stringify({ queue: { topRight: [], bottomRight: [], bottomLeft: [], topLeft: [] }})
9
-
10
6
  // Define chatgpt API
11
7
  const chatgpt = {
12
8
 
@@ -25,21 +21,21 @@ const chatgpt = {
25
21
  selectors: {
26
22
  btns: {
27
23
  continue: 'button:has(svg[class*=rotate] > path[d^="M4.47189"])',
28
- createImage: 'button[data-testid=composer-create-image]',
29
- deepResearch: 'button[data-testid=composer-deep-research]',
24
+ createImage: 'button[data-testid=composer-button-create-image]',
30
25
  login: 'button[data-testid*=login]',
31
26
  newChat: 'a[href="/"]:has(svg),' // Pencil button (when logged in)
32
27
  + 'button:has([d^="M3.06957"])', // Cycle Arrows button (in temp chat logged out)
33
28
  regen: 'button[data-testid*=regenerate],' // oval button in place of chatbar on errors
34
- // 'Try Again' entry of model selector below msg
35
- + 'div[role=menuitem] div:has(svg):has(path[d^="M3.06957"])',
36
- scroll: 'button:has(> svg > path[d^="M12 21C11.7348"])',
29
+ + 'button:has(use[href$="sprites-core-k5zux585.svg#ec66f0"])', // 'Try again...' button below msg
30
+ scroll: 'button:has(use[href$="sprites-core-k5zux585.svg#ac89a7"])',
37
31
  search: 'button[data-testid=composer-button-search]',
38
- reason: 'button[data-testid=composer-button-reason]',
39
32
  send: 'button[data-testid=send-button]',
40
- sidebar: 'div[style*=-sidebar-width] button[data-testid=close-sidebar-button], div[style*=-sidebar-rail-width] button[aria-controls=stage-slideover-sidebar]',
41
- stop: 'div:has(> svg > path[d^="M10 2.08496C14.3713"])',
42
- upload: 'button:has(> svg > path[d^="M12 3C12.5523"])',
33
+ sidebar: 'div[style*=-sidebar-width] button[data-testid=close-sidebar-button],'
34
+ + 'div[style*=-sidebar-rail-width] button[aria-controls=stage-slideover-sidebar]',
35
+ signup: 'button[data-testid=signup-button]',
36
+ stop: 'button[data-testid=stop-button]',
37
+ upload: 'div[data-testid=composer-action-file-upload],' // tall chatbar
38
+ + 'button#composer-plus-btn', // short chatbar
43
39
  voice: 'button[data-testid*=composer-speech-button]'
44
40
  },
45
41
  chatDivs: {
@@ -338,7 +334,7 @@ const chatgpt = {
338
334
  modalContainer.append(modal) ; document.body.append(modalContainer)
339
335
 
340
336
  // Enqueue alert
341
- let alertQueue = JSON.parse(localStorage.alertQueue)
337
+ let alertQueue = JSON.parse(localStorage.alertQueue ??= JSON.stringify([]))
342
338
  alertQueue.push(modalContainer.id)
343
339
  localStorage.alertQueue = JSON.stringify(alertQueue)
344
340
 
@@ -1383,7 +1379,8 @@ const chatgpt = {
1383
1379
  }
1384
1380
 
1385
1381
  // Enqueue notification
1386
- let notifyProps = JSON.parse(localStorage.notifyProps)
1382
+ let notifyProps = JSON.parse(localStorage.notifyProps
1383
+ ??= JSON.stringify({ queue: { topRight: [], bottomRight: [], bottomLeft: [], topLeft: [] }}))
1387
1384
  notifyProps.queue[notificationDiv.quadrant].push(notificationDiv.id)
1388
1385
  localStorage.notifyProps = JSON.stringify(notifyProps)
1389
1386
 
@@ -1642,10 +1639,10 @@ const chatgpt = {
1642
1639
  textArea.dispatchEvent(new Event('input', { bubbles: true })) // enable send button
1643
1640
  setTimeout(function delaySend() {
1644
1641
  const sendBtn = chatgpt.getSendButton()
1645
- if (!sendBtn?.hasAttribute('disabled')) { // send msg
1642
+ if (!sendBtn?.hasAttribute('disabled')) // send msg
1646
1643
  method.toLowerCase() == 'click' || chatgpt.browser.isMobile() ? sendBtn.click()
1647
1644
  : textArea.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }))
1648
- } else setTimeout(delaySend, 222)
1645
+ else setTimeout(delaySend, 222)
1649
1646
  }, 222)
1650
1647
  },
1651
1648
 
@@ -1839,15 +1836,13 @@ const chatgpt = {
1839
1836
  return console.error(`🤖 chatgpt.js >> Invalid element! Valid elems are [${validElems}]`)
1840
1837
 
1841
1838
  const newElem = document.createElement(elem == 'dropdown' ? 'select' : elem)
1842
- newElem.id = Math.floor(chatgpt.randomFloat() * 1000000) + Date.now() // Add random id to the element
1839
+ newElem.id = Math.floor(chatgpt.randomFloat() * 1000000) + Date.now()
1843
1840
 
1844
1841
  if (elem == 'button') {
1845
- newElem.textContent = attrs?.label && typeof attrs.label == 'string'
1846
- ? attrs.label
1847
- : 'chatgpt.js button'
1842
+ newElem.textContent = attrs?.label && typeof attrs.label == 'string' ? attrs.label : 'chatgpt.js button'
1848
1843
  const icon = document.createElement('img')
1849
- icon.src = attrs?.icon && typeof attrs.icon == 'string' // Can also be base64 encoded image string
1850
- ? attrs.icon // Add icon to button element if given, else default one
1844
+ icon.src = attrs?.icon && typeof attrs.icon == 'string' // can also be base64 encoded image string
1845
+ ? attrs.icon // add icon to button element if given, else default one
1851
1846
  : `${chatgpt.endpoints.assets}/starters/chrome/extension/icons/icon128.png`
1852
1847
  icon.width = 18
1853
1848
  newElem.firstChild.before(icon)
@@ -1855,9 +1850,9 @@ const chatgpt = {
1855
1850
  }
1856
1851
 
1857
1852
  else if (elem == 'dropdown') {
1858
- if (!attrs?.items || // There no are options to add
1853
+ if (!attrs?.items || // there no are options to add
1859
1854
  !Array.isArray(attrs.items) || // It's not an array
1860
- !attrs.items.length) // The array is empty
1855
+ !attrs.items.length) // the array is empty
1861
1856
  attrs.items = [{ text: '🤖 chatgpt.js option', value: 'chatgpt.js option value' }] // Set default dropdown entry
1862
1857
 
1863
1858
  if (!attrs.items.every(el => typeof el == 'object')) // The entries of the array are not objects
@@ -0,0 +1 @@
1
+ window.css={addRisingParticles(e,{lightScheme:i="gray",darkScheme:a="white"}={}){if(!e.querySelector("[id*=particles]")){let r=document.createElement("div");r.style.cssText="position: absolute ; top: 0 ; left: 0 ;height: 100% ; width: 100% ; border-radius: 15px ; overflow: clip ;z-index: -1",["sm","med","lg"].forEach(e=>{var t=document.createElement("div");t.id="undefined"!=typeof app&&app.config?.bgAnimationsDisabled?`particles-${e}-off`:`${"undefined"!=typeof env&&"dark"==(env.ui?.scheme||env.ui?.app?.scheme)?a:i}-particles-`+e,r.append(t)}),e.prepend(r)}},selectors:{extract(e,t="all"){if(!e||"object"!=typeof e)throw new TypeError("First parameter must be an object");var r=["all","css","xpath"];if(r.includes(t))return e=Object.values(e).flatMap(e=>e&&"object"==typeof e?this.extract(e,t):"string"==typeof e?[e]:[]),"css"==t?e.filter(e=>!e?.startsWith("//")):"xpath"==t?e.filter(e=>e?.startsWith("//")):e;throw new TypeError("Type must be one of: "+r.join(", "))},fromClasses(e){return e.toString().replace(/([:[\]\\])/g,"\\$1").replace(/^| /g,".")}}};
@@ -0,0 +1 @@
1
+ window.dom={create:{anchor(e,t,n={}){let r=document.createElement("a"),i={href:e,target:"_blank",rel:"noopener"},o={...i,...n};return Object.entries(o).forEach(([e,t])=>r.setAttribute(e,t)),t&&r.append(t),r},elem(e,t={}){var n,r=document.createElement(e);for(n in t)n in r?r[n]=t[n]:r.setAttribute(n,t[n]);return r},style(e,t={}){var n,r=document.createElement("style");for(n in r.setAttribute("type","text/css"),t)r.setAttribute(n,t[n]);return e&&(r.textContent=e),r},svgElem(e,t={}){var n,r=document.createElementNS("http://www.w3.org/2000/svg",e);for(n in t)r.setAttributeNS(null,n,t[n]);return r}},get:{computedSize(e,{dimension:t}={}){(e=e instanceof NodeList?[...e]:[].concat(e)).forEach(e=>{if(!(e instanceof Node))throw new Error(`Invalid elem: Element "${JSON.stringify(e)}" is not a valid DOM node`)});let n=["width","height"],r=[].concat(t||n),i=(r.forEach(e=>{if(!n.includes(e))throw new Error("Invalid dimension: Use 'width' or 'height'")}),{width:0,height:0});return e.forEach(t=>{let n=getComputedStyle(t);"none"!=n.display&&Object.keys(i).forEach(e=>{r.includes(e)&&(i[e]+=t.getBoundingClientRect()[e]+parseFloat(n["margin"+("width"==e?"Left":"Top")])+parseFloat(n["margin"+("width"==e?"Right":"Bottom")]))})}),1<r.length?i:i[r[0]]},computedHeight(e){return this.computedSize(e,{dimension:"height"})},computedWidth(e){return this.computedSize(e,{dimension:"width"})},loadedElem(i,{timeout:t=null}={}){var e=[new Promise(r=>{var e=document.querySelector(i);e?r(e):new MutationObserver((e,t)=>{var n=document.querySelector(i);n&&(t.disconnect(),r(n))}).observe(document.documentElement,{childList:!0,subtree:!0})})];return t&&e.push(new Promise(e=>setTimeout(()=>e(null),t))),Promise.race(e)}}};
@@ -1,4 +1,4 @@
1
- // Requires lib/<browser|chatgpt|dom|styles>.js + <app|env|configt>
1
+ // Requires lib/<browser|chatgpt|dom|styles>.js + <app|env>
2
2
 
3
3
  window.feedback = {
4
4
  notify(msg, pos = '', notifDuration = '', shadow = '') {
@@ -8,7 +8,7 @@ window.feedback = {
8
8
  if (foundState) msg = msg.replace(foundState, '')
9
9
 
10
10
  // Show notification
11
- chatgpt.notify(`${app.symbol} ${msg}`, pos ||( config.notifBottom ? 'bottom' : '' ),
11
+ chatgpt.notify(`${app.symbol} ${msg}`, pos ||( app.config.notifBottom ? 'bottom' : '' ),
12
12
  notifDuration, shadow || env.ui.scheme == 'light')
13
13
  const notif = document.querySelector('.chatgpt-notif:last-child')
14
14
  notif.classList.add(app.slug) // for styles.toast
@@ -1,4 +1,3 @@
1
- window.config = {}
2
1
  window.settings = {
3
2
 
4
3
  controls: {
@@ -40,15 +39,17 @@ window.settings = {
40
39
  },
41
40
 
42
41
  typeIsEnabled(key) { // for menu labels + notifs to return ON/OFF for type w/o suffix
42
+ app.config ??= {}
43
43
  const reInvertFlags = /disabled|hidden/i
44
44
  return reInvertFlags.test(key) // flag in control key name
45
45
  && !reInvertFlags.test(this.controls[key]?.label) // but not in label name
46
- ? !config[key] : config[key] // so invert since flag reps opposite type state, else don't
46
+ ? !app.config[key] : app.config[key] // so invert since flag reps opposite type state, else don't
47
47
  },
48
48
 
49
49
  load(...keys) {
50
+ app.config ??= {}
50
51
  return Promise.all(keys.flat().map(async key => // resolve promise when all keys load
51
- config[key] = processKey(key, (await chrome.storage.local.get(key))[key])))
52
+ app.config[key] = processKey(key, (await chrome.storage.local.get(key))[key])))
52
53
  function processKey(key, val) {
53
54
  const ctrl = settings.controls?.[key]
54
55
  if (val != undefined && ( // validate stored val
@@ -60,7 +61,8 @@ window.settings = {
60
61
  },
61
62
 
62
63
  save(key, val) {
64
+ app.config ??= {}
63
65
  chrome.storage.local.set({ [key]: val }) // save to Chrome extension storage
64
- config[key] = val // save to memory
66
+ app.config[key] = val // save to memory
65
67
  }
66
68
  };
@@ -2,8 +2,8 @@
2
2
  "manifest_version": 3,
3
3
  "name": "ChatGPT Extension",
4
4
  "short_name": "ChatGPT 🧩",
5
- "description": "A Chromium extension template to start using chatgpt.js like a boss!",
6
- "version": "2026.1.4",
5
+ "description": "A Chromium extension template to start using chatgpt.js like a champion",
6
+ "version": "2026.1.27",
7
7
  "homepage_url": "https://github.com/KudoAI/chatgpt.js-chrome-starter",
8
8
  "icons": { "16": "icons/icon16.png", "32": "icons/icon32.png", "64": "icons/icon64.png", "128": "icons/icon128.png" },
9
9
  "permissions": ["activeTab", "storage"],
@@ -5,7 +5,7 @@
5
5
  document.documentElement.classList.add('dark')
6
6
 
7
7
  // Import JS resources
8
- for (const resource of ['components/icons.js', 'lib/dom.js', 'lib/settings.js'])
8
+ for (const resource of ['components/icons.js', 'lib/css.min.js', 'lib/dom.min.js', 'lib/settings.js'])
9
9
  await import(chrome.runtime.getURL(resource))
10
10
 
11
11
  // Init DATA
@@ -54,7 +54,7 @@
54
54
 
55
55
  // Create/append slider elems
56
56
  entry.div.append(entry.slider = dom.create.elem('input', { class: 'slider', type: 'range',
57
- min: minVal, max: maxVal, value: config[entryData.key] }))
57
+ min: minVal, max: maxVal, value: app.config[entryData.key] }))
58
58
  entry.div.classList.remove('highlight-on-hover')
59
59
  if (entryData.step || env.browser.isFF) // use val from entryData or default to 2% in FF for being laggy
60
60
  entry.slider.step = entryData.step || ( 0.02 * entry.slider.max - entry.slider.min )
@@ -109,7 +109,7 @@
109
109
  category: () => toggleCategorySettingsVisiblity({ key: entryData.key }),
110
110
  toggle: () => {
111
111
  entry.leftElem.classList.toggle('on')
112
- settings.save(entryData.key, !config[entryData.key])
112
+ settings.save(entryData.key, !app.config[entryData.key])
113
113
  sync.configToUI({ updatedKey: entryData.key })
114
114
  requestAnimationFrame(() => notify(
115
115
  `${entryData.label} ${['OFF', 'ON'][+settings.typeIsEnabled(entryData.key)]}`))
@@ -162,7 +162,7 @@
162
162
  // Toolbar icon
163
163
  chrome.action.setIcon({ path: Object.fromEntries(
164
164
  Object.keys(chrome.runtime.getManifest().icons).map(dimension =>
165
- [dimension, `../icons/${ config.extensionDisabled ? 'faded/' : '' }icon${dimension}.png`]
165
+ [dimension, `../icons/${ app.config.extensionDisabled ? 'faded/' : '' }icon${dimension}.png`]
166
166
  ))})
167
167
 
168
168
  // Menu elems
@@ -170,8 +170,8 @@
170
170
  .forEach((elem, idx) => {
171
171
  if (elem.id && (elem.matches(`#${elem.id}:has(> div.link)`) || elem.id == 'aboutEntry'))
172
172
  return // never disable link/About entries
173
- elem.style.transition = config.extensionDisabled ? '' : 'opacity 0.15s ease-in'
174
- const toDisable = config.extensionDisabled || !depIsEnabled(elem.id)
173
+ elem.style.transition = app.config.extensionDisabled ? '' : 'opacity 0.15s ease-in'
174
+ const toDisable = app.config.extensionDisabled || !depIsEnabled(elem.id)
175
175
  if (elem.classList.contains('categorized-entries')) { // fade category strip
176
176
  elem.style.transition = toDisable ? 'none' : 'var(--border-transition)'
177
177
  elem.style.borderImage = elem.style.borderImage.replace(
@@ -223,7 +223,7 @@
223
223
  href: `https://cdn.jsdelivr.net/gh/adamlui/ai-web-extensions@71695ca/assets/styles/rising-particles/dist/${
224
224
  color}.min.css`
225
225
  })))
226
- dom.addRisingParticles(document.body, { lightScheme: env.menu.isDark ? 'white' : 'gray' })
226
+ css.addRisingParticles(document.body, { lightScheme: env.menu.isDark ? 'white' : 'gray' })
227
227
 
228
228
  // Init MASTER TOGGLE
229
229
  const masterToggle = {
@@ -232,9 +232,9 @@
232
232
  track: dom.create.elem('span', { class: 'track', style: 'position: relative ; top: 7.5px' })
233
233
  }
234
234
  masterToggle.div.append(masterToggle.switch) ; masterToggle.switch.append(masterToggle.track)
235
- await settings.load('extensionDisabled') ; masterToggle.switch.classList.toggle('on', !config.extensionDisabled)
235
+ await settings.load('extensionDisabled') ; masterToggle.switch.classList.toggle('on', !app.config.extensionDisabled)
236
236
  masterToggle.div.onclick = () => {
237
- masterToggle.switch.classList.toggle('on') ; settings.save('extensionDisabled', !config.extensionDisabled)
237
+ masterToggle.switch.classList.toggle('on') ; settings.save('extensionDisabled', !app.config.extensionDisabled)
238
238
  Object.keys(sync).forEach(key => sync[key]()) // sync fade + storage to UI
239
239
  notify(`${app.name} ${ this.checked ? 'ON' : 'OFF' }`)
240
240
  }
@@ -22,7 +22,7 @@
22
22
 
23
23
  # 🏛️ MIT License
24
24
 
25
- **Copyright © 2023–2025 [KudoAI](https://github.com/KudoAI) & contributors**
25
+ **Copyright © 2023–2026 [KudoAI](https://github.com/KudoAI) & contributors**
26
26
 
27
27
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
28
28
 
@@ -3,12 +3,12 @@
3
3
  // @description A Greasemonkey template to start using chatgpt.js like a boss
4
4
  // @author chatgpt.js
5
5
  // @namespace https://chatgpt.js.org
6
- // @version 2026.1.4
6
+ // @version 2026.1.27
7
7
  // @license MIT
8
8
  // @icon data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='180'%20height='180'%20fill='none'%3e%3cstyle%3e%20:root%20{%20--primary-fill:%20%23000;%20--secondary-fill:%20%23fff;%20}%20@media%20(prefers-color-scheme:%20dark)%20{%20:root%20{%20--primary-fill:%20%23fff;%20--secondary-fill:%20%23000;%20}%20}%20%3c/style%3e%3cg%20clip-path='url(%23a)'%3e%3crect%20width='180'%20height='180'%20fill='var(--primary-fill)'%20rx='90'%20/%3e%3cg%20clip-path='url(%23b)'%3e%3cpath%20fill='var(--secondary-fill)'%20d='M75.91%2073.628V62.232c0-.96.36-1.68%201.199-2.16l22.912-13.194c3.119-1.8%206.838-2.639%2010.676-2.639%2014.394%200%2023.511%2011.157%2023.511%2023.032%200%20.839%200%201.799-.12%202.758l-23.752-13.914c-1.439-.84-2.879-.84-4.318%200L75.91%2073.627Zm53.499%2044.383v-27.23c0-1.68-.72-2.88-2.159-3.719L97.142%2069.55l9.836-5.638c.839-.48%201.559-.48%202.399%200l22.912%2013.195c6.598%203.839%2011.035%2011.995%2011.035%2019.912%200%209.116-5.397%2017.513-13.915%2020.992v.001Zm-60.577-23.99-9.836-5.758c-.84-.48-1.2-1.2-1.2-2.16v-26.39c0-12.834%209.837-22.55%2023.152-22.55%205.039%200%209.716%201.679%2013.676%204.678L70.993%2055.516c-1.44.84-2.16%202.039-2.16%203.719v34.787-.002Zm21.173%2012.234L75.91%2098.339V81.546l14.095-7.917%2014.094%207.917v16.793l-14.094%207.916Zm9.056%2036.467c-5.038%200-9.716-1.68-13.675-4.678l23.631-13.676c1.439-.839%202.159-2.038%202.159-3.718V85.863l9.956%205.757c.84.48%201.2%201.2%201.2%202.16v26.389c0%2012.835-9.957%2022.552-23.27%2022.552v.001Zm-28.43-26.75L47.72%20102.778c-6.599-3.84-11.036-11.996-11.036-19.913%200-9.236%205.518-17.513%2014.034-20.992v27.35c0%201.68.72%202.879%202.16%203.718l29.989%2017.393-9.837%205.638c-.84.48-1.56.48-2.399%200Zm-1.318%2019.673c-13.555%200-23.512-10.196-23.512-22.792%200-.959.12-1.919.24-2.879l23.63%2013.675c1.44.84%202.88.84%204.32%200l30.108-17.392v11.395c0%20.96-.361%201.68-1.2%202.16l-22.912%2013.194c-3.119%201.8-6.837%202.639-10.675%202.639Zm29.748%2014.274c14.515%200%2026.63-10.316%2029.39-23.991%2013.434-3.479%2022.071-16.074%2022.071-28.91%200-8.396-3.598-16.553-10.076-22.43.6-2.52.96-5.039.96-7.557%200-17.153-13.915-29.99-29.989-29.99-3.239%200-6.358.48-9.477%201.56-5.398-5.278-12.835-8.637-20.992-8.637-14.515%200-26.63%2010.316-29.39%2023.991-13.434%203.48-22.07%2016.074-22.07%2028.91%200%208.396%203.598%2016.553%2010.075%2022.431-.6%202.519-.96%205.038-.96%207.556%200%2017.154%2013.915%2029.989%2029.99%2029.989%203.238%200%206.357-.479%209.476-1.559%205.397%205.278%2012.835%208.637%2020.992%208.637Z'%20/%3e%3c/g%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='a'%3e%3cpath%20d='M0%200h180v180H0z'%20/%3e%3c/clipPath%3e%3cclipPath%20id='b'%3e%3cpath%20d='M29.487%2029.964h121.035v119.954H29.487z'%20/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e
9
9
  // @icon64 data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='180'%20height='180'%20fill='none'%3e%3cstyle%3e%20:root%20{%20--primary-fill:%20%23000;%20--secondary-fill:%20%23fff;%20}%20@media%20(prefers-color-scheme:%20dark)%20{%20:root%20{%20--primary-fill:%20%23fff;%20--secondary-fill:%20%23000;%20}%20}%20%3c/style%3e%3cg%20clip-path='url(%23a)'%3e%3crect%20width='180'%20height='180'%20fill='var(--primary-fill)'%20rx='90'%20/%3e%3cg%20clip-path='url(%23b)'%3e%3cpath%20fill='var(--secondary-fill)'%20d='M75.91%2073.628V62.232c0-.96.36-1.68%201.199-2.16l22.912-13.194c3.119-1.8%206.838-2.639%2010.676-2.639%2014.394%200%2023.511%2011.157%2023.511%2023.032%200%20.839%200%201.799-.12%202.758l-23.752-13.914c-1.439-.84-2.879-.84-4.318%200L75.91%2073.627Zm53.499%2044.383v-27.23c0-1.68-.72-2.88-2.159-3.719L97.142%2069.55l9.836-5.638c.839-.48%201.559-.48%202.399%200l22.912%2013.195c6.598%203.839%2011.035%2011.995%2011.035%2019.912%200%209.116-5.397%2017.513-13.915%2020.992v.001Zm-60.577-23.99-9.836-5.758c-.84-.48-1.2-1.2-1.2-2.16v-26.39c0-12.834%209.837-22.55%2023.152-22.55%205.039%200%209.716%201.679%2013.676%204.678L70.993%2055.516c-1.44.84-2.16%202.039-2.16%203.719v34.787-.002Zm21.173%2012.234L75.91%2098.339V81.546l14.095-7.917%2014.094%207.917v16.793l-14.094%207.916Zm9.056%2036.467c-5.038%200-9.716-1.68-13.675-4.678l23.631-13.676c1.439-.839%202.159-2.038%202.159-3.718V85.863l9.956%205.757c.84.48%201.2%201.2%201.2%202.16v26.389c0%2012.835-9.957%2022.552-23.27%2022.552v.001Zm-28.43-26.75L47.72%20102.778c-6.599-3.84-11.036-11.996-11.036-19.913%200-9.236%205.518-17.513%2014.034-20.992v27.35c0%201.68.72%202.879%202.16%203.718l29.989%2017.393-9.837%205.638c-.84.48-1.56.48-2.399%200Zm-1.318%2019.673c-13.555%200-23.512-10.196-23.512-22.792%200-.959.12-1.919.24-2.879l23.63%2013.675c1.44.84%202.88.84%204.32%200l30.108-17.392v11.395c0%20.96-.361%201.68-1.2%202.16l-22.912%2013.194c-3.119%201.8-6.837%202.639-10.675%202.639Zm29.748%2014.274c14.515%200%2026.63-10.316%2029.39-23.991%2013.434-3.479%2022.071-16.074%2022.071-28.91%200-8.396-3.598-16.553-10.076-22.43.6-2.52.96-5.039.96-7.557%200-17.153-13.915-29.99-29.989-29.99-3.239%200-6.358.48-9.477%201.56-5.398-5.278-12.835-8.637-20.992-8.637-14.515%200-26.63%2010.316-29.39%2023.991-13.434%203.48-22.07%2016.074-22.07%2028.91%200%208.396%203.598%2016.553%2010.075%2022.431-.6%202.519-.96%205.038-.96%207.556%200%2017.154%2013.915%2029.989%2029.99%2029.989%203.238%200%206.357-.479%209.476-1.559%205.397%205.278%2012.835%208.637%2020.992%208.637Z'%20/%3e%3c/g%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='a'%3e%3cpath%20d='M0%200h180v180H0z'%20/%3e%3c/clipPath%3e%3cclipPath%20id='b'%3e%3cpath%20d='M29.487%2029.964h121.035v119.954H29.487z'%20/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e
10
10
  // @match *://chatgpt.com/*
11
- // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.5/dist/chatgpt.min.js
11
+ // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.9.0/dist/chatgpt.min.js
12
12
  // @grant GM_getValue
13
13
  // @grant GM_setValue
14
14
  // @noframes
@@ -16,7 +16,7 @@
16
16
  // @supportURL https://github.com/KudoAI/chatgpt.js-greasemonkey-starter/issues
17
17
  // ==/UserScript==
18
18
 
19
- // NOTE: This script relies on the powerful chatgpt.js library @ https://chatgpt.js.org © 2023–2025 KudoAI & contributors under the MIT license
19
+ // NOTE: This script relies on the powerful chatgpt.js library @ https://chatgpt.js.org © 2023–2026 KudoAI & contributors under the MIT license
20
20
 
21
21
  (async () => {
22
22
  'use strict'
@@ -1,114 +0,0 @@
1
- // Copyright © 2023–2025 Adam Lui (https://github.com/adamlui) under the MIT license
2
- // Source: https://github.com/adamlui/ai-web-extensions/blob/main/assets/lib/dom.js/src/dom.js
3
-
4
- window.dom = {
5
-
6
- addRisingParticles(targetNode, { lightScheme = 'gray', darkScheme = 'white' } = {}) {
7
- // * Requires https://assets.aiwebextensions.com/styles/rising-particles/dist/<lightScheme>.min.css
8
-
9
- if (targetNode.querySelector('[id*=particles]')) return
10
- const particlesDivsWrapper = document.createElement('div')
11
- particlesDivsWrapper.style.cssText = (
12
- 'position: absolute ; top: 0 ; left: 0 ;' // hug targetNode's top-left corner
13
- + 'height: 100% ; width: 100% ; border-radius: 15px ; overflow: clip ;' // bound innards exactly by targetNode
14
- + 'z-index: -1' ) // allow interactive elems to be clicked
15
- ;['sm', 'med', 'lg'].forEach(particleSize => {
16
- const particlesDiv = document.createElement('div')
17
- particlesDiv.id = config?.bgAnimationsDisabled ? `particles-${particleSize}-off`
18
- : `${( env?.ui?.scheme || env?.ui?.app?.scheme ) == 'dark' ? darkScheme
19
- : lightScheme }-particles-${particleSize}`
20
- particlesDivsWrapper.append(particlesDiv)
21
- })
22
- targetNode.prepend(particlesDivsWrapper)
23
- },
24
-
25
- create: {
26
- anchor(linkHref, displayContent, attrs = {}) {
27
- const anchor = document.createElement('a'),
28
- defaultAttrs = { href: linkHref, target: '_blank', rel: 'noopener' },
29
- finalAttrs = { ...defaultAttrs, ...attrs }
30
- Object.entries(finalAttrs).forEach(([attr, value]) => anchor.setAttribute(attr, value))
31
- if (displayContent) anchor.append(displayContent)
32
- return anchor
33
- },
34
-
35
- elem(elemType, attrs = {}) {
36
- const elem = document.createElement(elemType)
37
- for (const attr in attrs) {
38
- if (attr in elem) elem[attr] = attrs[attr]
39
- else elem.setAttribute(attr, attrs[attr])
40
- }
41
- return elem
42
- },
43
-
44
- style(content, attrs = {}) {
45
- const style = document.createElement('style')
46
- style.setAttribute('type', 'text/css') // support older browsers
47
- for (const attr in attrs) style.setAttribute(attr, attrs[attr])
48
- if (content) style.textContent = content
49
- return style
50
- },
51
-
52
- svgElem(type, attrs = {}) {
53
- const elem = document.createElementNS('http://www.w3.org/2000/svg', type)
54
- for (const attr in attrs) elem.setAttributeNS(null, attr, attrs[attr])
55
- return elem
56
- }
57
- },
58
-
59
- cssSelectorize(classList) {
60
- return classList.toString()
61
- .replace(/([:[\]\\])/g, '\\$1') // escape special chars :[]\
62
- .replace(/^| /g, '.') // prefix w/ dot, convert spaces to dots
63
- },
64
-
65
- get: {
66
-
67
- computedSize(elems, { dimension } = {}) { // total width/height of elems (including margins)
68
- // * Returns { width: totalWidth, height: totalHeight } if no dimension passed
69
- // * Returns float if { dimension: 'width' | 'height' } passed
70
-
71
- // Validate args
72
- elems = elems instanceof NodeList ? [...elems] : [].concat(elems)
73
- elems.forEach(elem => { if (!(elem instanceof Node))
74
- throw new Error(`Invalid elem: Element "${JSON.stringify(elem)}" is not a valid DOM node`) })
75
- const validDimensions = ['width', 'height'], dimensionsToCompute = [].concat(dimension || validDimensions)
76
- dimensionsToCompute.forEach(dimension => { if (!validDimensions.includes(dimension))
77
- throw new Error('Invalid dimension: Use \'width\' or \'height\'') })
78
-
79
- // Compute dimensions
80
- const computedDimensions = { width: 0, height: 0 }
81
- elems.forEach(elem => {
82
- const elemStyle = getComputedStyle(elem) ; if (elemStyle.display == 'none') return
83
- Object.keys(computedDimensions).forEach(dimension => {
84
- if (dimensionsToCompute.includes(dimension))
85
- computedDimensions[dimension] += elem.getBoundingClientRect()[dimension]
86
- + parseFloat(elemStyle[`margin${dimension == 'width' ? 'Left' : 'Top'}`])
87
- + parseFloat(elemStyle[`margin${dimension == 'width' ? 'Right' : 'Bottom'}`])
88
- })
89
- })
90
-
91
- // Return computed dimensions
92
- return dimensionsToCompute.length > 1 ? computedDimensions // obj w/ width/height
93
- : computedDimensions[dimensionsToCompute[0]] // single total val
94
- },
95
-
96
- computedHeight(elems) { return this.computedSize(elems, { dimension: 'height' }) }, // including margins
97
- computedWidth(elems) { return this.computedSize(elems, { dimension: 'width' }) }, // including margins
98
-
99
- loadedElem(selector, { timeout = null } = {}) {
100
- const raceEntries = [
101
- new Promise(resolve => { // when elem loads
102
- const elem = document.querySelector(selector)
103
- if (elem) resolve(elem)
104
- else new MutationObserver((_, obs) => {
105
- const elem = document.querySelector(selector)
106
- if (elem) { obs.disconnect() ; resolve(elem) }
107
- }).observe(document.documentElement, { childList: true, subtree: true })
108
- })
109
- ]
110
- if (timeout) raceEntries.push(new Promise(resolve => setTimeout(() => resolve(null), timeout)))
111
- return Promise.race(raceEntries)
112
- }
113
- }
114
- };