@kudoai/chatgpt.js 3.5.0 → 3.6.1
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 +1 -1
- package/README.md +147 -88
- package/chatgpt.js +127 -103
- package/dist/chatgpt.min.js +28 -4
- package/docs/README.md +154 -88
- package/docs/SECURITY.md +15 -15
- package/docs/USERGUIDE.md +19 -5
- package/package.json +10 -6
- package/starters/chrome/LICENSE.md +3 -3
- package/starters/chrome/docs/README.md +5 -5
- package/starters/chrome/docs/SECURITY.md +3 -5
- package/starters/chrome/extension/components/icons.js +2 -5
- package/starters/chrome/extension/components/modals.js +90 -87
- package/starters/chrome/extension/content.js +18 -11
- package/starters/chrome/extension/icons/faded/icon128.png +0 -0
- package/starters/chrome/extension/icons/faded/icon16.png +0 -0
- package/starters/chrome/extension/icons/faded/icon32.png +0 -0
- package/starters/chrome/extension/icons/faded/icon64.png +0 -0
- package/starters/chrome/extension/lib/chatgpt.js +127 -103
- package/starters/chrome/extension/lib/dom.js +90 -16
- package/starters/chrome/extension/lib/settings.js +7 -8
- package/starters/chrome/extension/manifest.json +1 -1
- package/starters/chrome/extension/popup/controller.js +7 -7
- package/starters/chrome/extension/popup/index.html +1 -1
- package/starters/chrome/extension/popup/style.css +3 -4
- package/starters/chrome/extension/service-worker.js +1 -1
- package/starters/chrome/images/icons/question-mark/icon16.png +0 -0
- package/starters/chrome/images/icons/question-mark/icon512.png +0 -0
- package/starters/docs/LICENSE.md +21 -1
- package/starters/docs/README.md +19 -6
- package/starters/greasemonkey/LICENSE.md +3 -3
- package/starters/greasemonkey/chatgpt.js-greasemonkey-starter.user.js +5 -6
- package/starters/greasemonkey/docs/README.md +1 -1
- package/starters/greasemonkey/docs/SECURITY.md +3 -5
- /package/starters/greasemonkey/{media → assets}/images/icons/robot/icon48.png +0 -0
- /package/starters/greasemonkey/{media → assets}/images/icons/robot/icon64.png +0 -0
- /package/starters/greasemonkey/{media → assets}/images/screenshots/chatgpt-userscript-on.png +0 -0
package/chatgpt.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// © 2023–
|
|
1
|
+
// © 2023–2025 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
|
|
@@ -23,7 +23,7 @@ const chatgpt = {
|
|
|
23
23
|
actAs(persona) {
|
|
24
24
|
// Prompts ChatGPT to act as a persona from https://github.com/KudoAI/chat-prompts/blob/main/personas.json
|
|
25
25
|
|
|
26
|
-
const promptsUrl = 'https://
|
|
26
|
+
const promptsUrl = 'https://cdn.jsdelivr.net/gh/KudoAI/chat-prompts/dist/personas.min.json';
|
|
27
27
|
return new Promise((resolve, reject) => {
|
|
28
28
|
const xhr = new XMLHttpRequest();
|
|
29
29
|
xhr.open('GET', promptsUrl, true); xhr.send();
|
|
@@ -73,7 +73,7 @@ const chatgpt = {
|
|
|
73
73
|
|
|
74
74
|
dismiss: {
|
|
75
75
|
click(event) {
|
|
76
|
-
if (event.target == event.currentTarget || event.target.closest('[class
|
|
76
|
+
if (event.target == event.currentTarget || event.target.closest('[class*=-close-btn]'))
|
|
77
77
|
dismissAlert()
|
|
78
78
|
},
|
|
79
79
|
|
|
@@ -97,7 +97,8 @@ const chatgpt = {
|
|
|
97
97
|
if (event.button != 0) return // prevent non-left-click drag
|
|
98
98
|
if (getComputedStyle(event.target).cursor == 'pointer') return // prevent drag on interactive elems
|
|
99
99
|
chatgpt.draggableElem = event.currentTarget
|
|
100
|
-
chatgpt.draggableElem.style
|
|
100
|
+
Object.assign(chatgpt.draggableElem.style, {
|
|
101
|
+
cursor: 'grabbing', transition: '0.1s', willChange: 'transform', transform: 'scale(1.05)' })
|
|
101
102
|
event.preventDefault(); // prevent sub-elems like icons being draggable
|
|
102
103
|
['mousemove', 'mouseup'].forEach(eventType =>
|
|
103
104
|
document.addEventListener(eventType, handlers.drag[eventType]))
|
|
@@ -114,7 +115,8 @@ const chatgpt = {
|
|
|
114
115
|
},
|
|
115
116
|
|
|
116
117
|
mouseup() { // remove listeners, reset chatgpt.draggableElem
|
|
117
|
-
chatgpt.draggableElem.style
|
|
118
|
+
Object.assign(chatgpt.draggableElem.style, {
|
|
119
|
+
cursor: 'inherit', transition: 'inherit', willChange: 'auto', transform: 'scale(1)' });
|
|
118
120
|
['mousemove', 'mouseup'].forEach(eventType =>
|
|
119
121
|
document.removeEventListener(eventType, handlers.drag[eventType]))
|
|
120
122
|
chatgpt.draggableElem = null
|
|
@@ -131,7 +133,7 @@ const chatgpt = {
|
|
|
131
133
|
modalMessage = document.createElement('p');
|
|
132
134
|
|
|
133
135
|
// Create/append/update modal style (if missing or outdated)
|
|
134
|
-
const thisUpdated =
|
|
136
|
+
const thisUpdated = 1735768363880 // timestamp of last edit for this file's `modalStyle`
|
|
135
137
|
let modalStyle = document.querySelector('#chatgpt-modal-style'); // try to select existing style
|
|
136
138
|
if (!modalStyle || parseInt(modalStyle.getAttribute('last-updated'), 10) < thisUpdated) { // if missing or outdated
|
|
137
139
|
if (!modalStyle) { // outright missing, create/id/attr/append it first
|
|
@@ -140,14 +142,21 @@ const chatgpt = {
|
|
|
140
142
|
document.head.append(modalStyle);
|
|
141
143
|
}
|
|
142
144
|
modalStyle.innerText = ( // update prev/new style contents
|
|
143
|
-
'.
|
|
145
|
+
'.chatgpt-modal {' // vars
|
|
146
|
+
+ '--transition: opacity 0.65s cubic-bezier(.165,.84,.44,1),' // for fade-in
|
|
147
|
+
+ 'transform 0.55s cubic-bezier(.165,.84,.44,1) ;' // for move-in
|
|
148
|
+
+ '--bg-transition: background-color 0.25s ease }' // for bg dim
|
|
149
|
+
|
|
150
|
+
+ '.no-mobile-tap-outline { outline: none ; -webkit-tap-highlight-color: transparent }'
|
|
144
151
|
|
|
145
152
|
// Background styles
|
|
146
153
|
+ '.chatgpt-modal {'
|
|
147
154
|
+ 'pointer-events: auto ;' // override any disabling from site modals (like guest login spam)
|
|
148
155
|
+ 'position: fixed ; top: 0 ; left: 0 ; width: 100% ; height: 100% ;' // expand to full view-port
|
|
149
|
-
+ '
|
|
150
|
-
+ '
|
|
156
|
+
+ 'display: flex ; justify-content: center ; align-items: center ; z-index: 9999 ;' // align
|
|
157
|
+
+ 'transition: var(--bg-transition) ;' // for bg dim
|
|
158
|
+
+ '-webkit-transition: var(--bg-transition) ; -moz-transition: var(--bg-transition) ;'
|
|
159
|
+
+ '-o-transition: var(--bg-transition) ; -ms-transition: var(--bg-transition) }'
|
|
151
160
|
|
|
152
161
|
// Alert styles
|
|
153
162
|
+ '.chatgpt-modal > div {'
|
|
@@ -157,18 +166,23 @@ const chatgpt = {
|
|
|
157
166
|
+ `color: ${ scheme == 'dark' ? 'white' : 'black' };`
|
|
158
167
|
+ `background-color: ${ scheme == 'dark' ? 'black' : 'white' };`
|
|
159
168
|
+ 'transform: translateX(-3px) translateY(7px) ;' // offset to move-in from
|
|
160
|
-
+ '
|
|
161
|
-
|
|
162
|
-
+
|
|
163
|
-
|
|
164
|
-
+ '
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
+
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
+ 'max-width: 75vw ; word-wrap: break-word ; border-radius: 15px ;'
|
|
170
|
+
+ 'padding: 20px ; margin: 12px 23px ;'
|
|
171
|
+
+ `--shadow: 0 30px 60px rgba(0,0,0,0.12) ; box-shadow: var(--shadow) ;
|
|
172
|
+
-webkit-box-shadow: var(--shadow) ; -moz-box-shadow: var(--shadow) ;`
|
|
173
|
+
+ 'user-select: none ; -webkit-user-select: none ; -moz-user-select: none ; -o-user-select: none ;'
|
|
174
|
+
+ '-ms-user-select: none ;'
|
|
175
|
+
+ 'transition: var(--transition) ;' // for fade-in + move-in
|
|
176
|
+
+ '-webkit-transition: var(--transition) ; -moz-transition: var(--transition) ;'
|
|
177
|
+
+ '-o-transition: var(--transition) ; -ms-transition: var(--transition) }'
|
|
178
|
+
+ `.chatgpt-modal h2 { margin-bottom: 9px }
|
|
179
|
+
.chatgpt-modal a { color: ${ scheme == 'dark' ? '#00cfff' : '#1e9ebb' }}
|
|
180
|
+
.chatgpt-modal a:hover { text-decoration: underline }
|
|
181
|
+
.chatgpt-modal.animated > div {
|
|
182
|
+
z-index: 13456 ; opacity: 0.98 ; transform: translateX(0) translateY(0) }
|
|
183
|
+
@keyframes alert-zoom-fade-out {
|
|
184
|
+
0% { opacity: 1 } 50% { opacity: 0.25 ; transform: scale(1.05) }
|
|
185
|
+
100% { opacity: 0 ; transform: scale(1.35) }}`
|
|
172
186
|
|
|
173
187
|
// Button styles
|
|
174
188
|
+ '.modal-buttons { display: flex ; justify-content: flex-end ; margin: 20px -5px -3px 0 ;'
|
|
@@ -181,9 +195,11 @@ const chatgpt = {
|
|
|
181
195
|
+ `border: 1px solid ${ scheme == 'dark' ? 'white' : 'black' } ;`
|
|
182
196
|
+ `background: ${ scheme == 'dark' ? 'white' : 'black' } ;`
|
|
183
197
|
+ `color: ${ scheme == 'dark' ? 'black' : 'white' }}`
|
|
184
|
-
+
|
|
185
|
-
|
|
186
|
-
|
|
198
|
+
+ `.chatgpt-modal button:hover {
|
|
199
|
+
color: #3d5d71 ; border-color: #6d9cb9 ;
|
|
200
|
+
background-color: ${ scheme == 'dark' ? '#00cfff' : '#9cdaff' };
|
|
201
|
+
--shadow: 2px 1px ${ scheme == 'dark' ? '54px #00cfff' : '30px #9cdaff' };
|
|
202
|
+
box-shadow: var(--shadow) ; box-shadow: var(--shadow) ; box-shadow: var(--shadow) }`
|
|
187
203
|
+ '.modal-close-btn {'
|
|
188
204
|
+ 'cursor: pointer ; width: 29px ; height: 29px ; border-radius: 17px ;'
|
|
189
205
|
+ 'float: right ; position: relative ; right: -6px ; top: -5px }'
|
|
@@ -191,17 +207,18 @@ const chatgpt = {
|
|
|
191
207
|
+ `.modal-close-btn:hover { background-color: #f2f2f2${ scheme == 'dark' ? '00' : '' }}`
|
|
192
208
|
|
|
193
209
|
// Checkbox styles
|
|
194
|
-
+
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
210
|
+
+ `.chatgpt-modal .checkbox-group { margin-top: 15px }
|
|
211
|
+
.chatgpt-modal .checkbox-group label {
|
|
212
|
+
font-size: .7rem ; margin: -.04rem 0 0px .3rem
|
|
213
|
+
color: ${ scheme == 'dark' ? '#e1e1e1' : '#1e1e1e' }}
|
|
214
|
+
.chatgpt-modal input[type=checkbox] { transform: scale(0.7) ;
|
|
215
|
+
border: 1px solid ${ scheme == 'dark' ? 'white' : 'black' }}
|
|
216
|
+
.chatgpt-modal input[type=checkbox]:checked {
|
|
217
|
+
border: 1px solid ${ scheme == 'dark' ? 'white' : 'black' } ;
|
|
218
|
+
background-color: black ; position: inherit }
|
|
219
|
+
.chatgpt-modal input[type=checkbox]:focus {
|
|
220
|
+
outline: none ; box-shadow: none ; -webkit-box-shadow: none ; -moz-box-shadow: none }`
|
|
221
|
+
)
|
|
205
222
|
}
|
|
206
223
|
|
|
207
224
|
// Insert text into elements
|
|
@@ -268,7 +285,7 @@ const chatgpt = {
|
|
|
268
285
|
closeSVG.append(closeSVGpath); closeBtn.append(closeSVG);
|
|
269
286
|
|
|
270
287
|
// Assemble/append div
|
|
271
|
-
const modalElems = [closeBtn, modalTitle, modalMessage,
|
|
288
|
+
const modalElems = [closeBtn, modalTitle, modalMessage, checkboxDiv, modalButtons ];
|
|
272
289
|
modalElems.forEach((elem) => { modal.append(elem); });
|
|
273
290
|
modal.style.width = `${ width || 458 }px`;
|
|
274
291
|
modalContainer.append(modal); document.body.append(modalContainer);
|
|
@@ -283,7 +300,7 @@ const chatgpt = {
|
|
|
283
300
|
if (alertQueue.length === 1) {
|
|
284
301
|
modalContainer.style.display = '';
|
|
285
302
|
setTimeout(() => { // dim bg
|
|
286
|
-
modal.parentNode.style.backgroundColor = `rgba(67,
|
|
303
|
+
modal.parentNode.style.backgroundColor = `rgba(67,70,72,${ scheme == 'dark' ? 0.62 : 0.33 })`
|
|
287
304
|
modal.parentNode.classList.add('animated')
|
|
288
305
|
}, 100) // delay for transition fx
|
|
289
306
|
}
|
|
@@ -296,30 +313,29 @@ const chatgpt = {
|
|
|
296
313
|
|
|
297
314
|
// Define alert dismisser
|
|
298
315
|
const dismissAlert = () => {
|
|
299
|
-
modalContainer.style.backgroundColor = 'transparent'
|
|
300
|
-
modal.style.animation = 'alert-zoom-fade-out 0.
|
|
301
|
-
|
|
316
|
+
modalContainer.style.backgroundColor = 'transparent'
|
|
317
|
+
modal.style.animation = 'alert-zoom-fade-out 0.165s ease-out'
|
|
318
|
+
modal.onanimationend = () => {
|
|
302
319
|
|
|
303
320
|
// Remove alert
|
|
304
|
-
modalContainer.remove()
|
|
305
|
-
alertQueue = JSON.parse(localStorage.alertQueue)
|
|
306
|
-
alertQueue.shift()
|
|
307
|
-
localStorage.alertQueue = JSON.stringify(alertQueue)
|
|
308
|
-
document.removeEventListener('keydown', handlers.dismiss.key)
|
|
321
|
+
modalContainer.remove() // ...from DOM
|
|
322
|
+
alertQueue = JSON.parse(localStorage.alertQueue)
|
|
323
|
+
alertQueue.shift() // + memory
|
|
324
|
+
localStorage.alertQueue = JSON.stringify(alertQueue) // + storage
|
|
325
|
+
document.removeEventListener('keydown', handlers.dismiss.key) // prevent memory leaks
|
|
309
326
|
|
|
310
327
|
// Check for pending alerts in queue
|
|
311
328
|
if (alertQueue.length > 0) {
|
|
312
|
-
const nextAlert = document.getElementById(alertQueue[0])
|
|
329
|
+
const nextAlert = document.getElementById(alertQueue[0])
|
|
313
330
|
setTimeout(() => {
|
|
314
|
-
nextAlert.style.display = ''
|
|
315
|
-
setTimeout(() =>
|
|
316
|
-
}, 500)
|
|
331
|
+
nextAlert.style.display = ''
|
|
332
|
+
setTimeout(() => nextAlert.classList.add('animated'), 100)
|
|
333
|
+
}, 500)
|
|
317
334
|
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
318
337
|
|
|
319
|
-
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
return modalContainer.id; // if assignment used
|
|
338
|
+
return modalContainer.id // if assignment used
|
|
323
339
|
},
|
|
324
340
|
|
|
325
341
|
async askAndGetReply(query) {
|
|
@@ -592,7 +608,7 @@ const chatgpt = {
|
|
|
592
608
|
// Create transcript from active chat
|
|
593
609
|
if (chatToGet == 'active' && /\/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/.test(window.location.href)) {
|
|
594
610
|
const chatDivs = document.querySelectorAll('main > div > div > div > div > div > div[class*=group]');
|
|
595
|
-
if (chatDivs.length
|
|
611
|
+
if (!chatDivs.length) return console.error('Chat is empty!');
|
|
596
612
|
const msgs = []; let isUserMsg = true;
|
|
597
613
|
chatDivs.forEach((div) => {
|
|
598
614
|
const sender = isUserMsg ? 'USER' : 'CHATGPT'; isUserMsg = !isUserMsg;
|
|
@@ -970,14 +986,14 @@ const chatgpt = {
|
|
|
970
986
|
|
|
971
987
|
history: {
|
|
972
988
|
async isLoaded(timeout = null) {
|
|
973
|
-
const timeoutPromise = timeout ? new Promise(resolve => setTimeout(() => resolve(false), timeout)) : null
|
|
989
|
+
const timeoutPromise = timeout ? new Promise(resolve => setTimeout(() => resolve(false), timeout)) : null
|
|
974
990
|
const isLoadedPromise = new Promise(resolve => {
|
|
975
|
-
if (document.querySelector('nav')) resolve(true)
|
|
991
|
+
if (document.querySelector('nav')) resolve(true)
|
|
976
992
|
else new MutationObserver((_, obs) => {
|
|
977
|
-
if (document.querySelector('nav')) { obs.disconnect(); resolve(true)
|
|
978
|
-
}).observe(document.
|
|
979
|
-
})
|
|
980
|
-
return await ( timeoutPromise ? Promise.race([isLoadedPromise, timeoutPromise]) : isLoadedPromise )
|
|
993
|
+
if (document.querySelector('nav')) { obs.disconnect() ; resolve(true) }
|
|
994
|
+
}).observe(document.documentElement, { childList: true, subtree: true })
|
|
995
|
+
})
|
|
996
|
+
return await ( timeoutPromise ? Promise.race([isLoadedPromise, timeoutPromise]) : isLoadedPromise )
|
|
981
997
|
}
|
|
982
998
|
},
|
|
983
999
|
|
|
@@ -1106,7 +1122,7 @@ const chatgpt = {
|
|
|
1106
1122
|
}
|
|
1107
1123
|
},
|
|
1108
1124
|
|
|
1109
|
-
isDarkMode() { return document.documentElement.
|
|
1125
|
+
isDarkMode() { return document.documentElement.className.includes('dark') },
|
|
1110
1126
|
isFullScreen() { return chatgpt.browser.isFullScreen(); },
|
|
1111
1127
|
|
|
1112
1128
|
async isIdle(timeout = null) {
|
|
@@ -1138,17 +1154,18 @@ const chatgpt = {
|
|
|
1138
1154
|
},
|
|
1139
1155
|
|
|
1140
1156
|
async isLoaded(timeout = null) {
|
|
1141
|
-
const timeoutPromise = timeout ? new Promise(resolve => setTimeout(() => resolve(false), timeout)) : null
|
|
1157
|
+
const timeoutPromise = timeout ? new Promise(resolve => setTimeout(() => resolve(false), timeout)) : null
|
|
1142
1158
|
const isLoadedPromise = new Promise(resolve => {
|
|
1143
|
-
if (chatgpt.getNewChatBtn()) resolve(true)
|
|
1159
|
+
if (chatgpt.getNewChatBtn()) resolve(true)
|
|
1144
1160
|
else new MutationObserver((_, obs) => {
|
|
1145
|
-
if (chatgpt.getNewChatBtn()) { obs.disconnect(); resolve(true)
|
|
1146
|
-
}).observe(document.
|
|
1147
|
-
})
|
|
1148
|
-
return await ( timeoutPromise ? Promise.race([isLoadedPromise, timeoutPromise]) : isLoadedPromise )
|
|
1161
|
+
if (chatgpt.getNewChatBtn()) { obs.disconnect() ; resolve(true) }
|
|
1162
|
+
}).observe(document.documentElement, { childList: true, subtree: true })
|
|
1163
|
+
})
|
|
1164
|
+
return await ( timeoutPromise ? Promise.race([isLoadedPromise, timeoutPromise]) : isLoadedPromise )
|
|
1149
1165
|
},
|
|
1150
1166
|
|
|
1151
1167
|
isLightMode() { return document.documentElement.classList.toString().includes('light'); },
|
|
1168
|
+
isTyping() { return !!this.getStopButton() },
|
|
1152
1169
|
|
|
1153
1170
|
logout() { window.location.href = 'https://chat.openai.com/auth/logout'; },
|
|
1154
1171
|
|
|
@@ -1287,7 +1304,7 @@ const chatgpt = {
|
|
|
1287
1304
|
+ (notificationDiv.isRight ? 'Right' : 'Left');
|
|
1288
1305
|
|
|
1289
1306
|
// Create/append/update notification style (if missing or outdated)
|
|
1290
|
-
const thisUpdated =
|
|
1307
|
+
const thisUpdated = 1735767823541 // timestamp of last edit for this file's `notifStyle`
|
|
1291
1308
|
let notifStyle = document.querySelector('#chatgpt-notif-style'); // try to select existing style
|
|
1292
1309
|
if (!notifStyle || parseInt(notifStyle.getAttribute('last-updated'), 10) < thisUpdated) { // if missing or outdated
|
|
1293
1310
|
if (!notifStyle) { // outright missing, create/id/attr/append it first
|
|
@@ -1300,12 +1317,18 @@ const chatgpt = {
|
|
|
1300
1317
|
+ 'font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC",'
|
|
1301
1318
|
+ '"Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", sans-serif ;'
|
|
1302
1319
|
+ '.no-mobile-tap-outline { outline: none ; -webkit-tap-highlight-color: transparent }'
|
|
1303
|
-
+ 'background-color: black ; padding: 10px 13px 10px 18px ;
|
|
1320
|
+
+ 'background-color: black ; padding: 10px 13px 10px 18px ;' // bubble style
|
|
1321
|
+
+ 'border-radius: 11px ; border: 1px solid #f5f5f7 ;'
|
|
1304
1322
|
+ 'opacity: 0 ; position: fixed ; z-index: 9999 ; font-size: 1.8rem ; color: white ;' // visibility
|
|
1305
|
-
+ '
|
|
1306
|
-
|
|
1307
|
-
+
|
|
1308
|
-
|
|
1323
|
+
+ 'user-select: none ; -webkit-user-select: none ; -moz-user-select: none ; -o-user-select: none ;'
|
|
1324
|
+
+ '-ms-user-select: none ;'
|
|
1325
|
+
+ `transform: translateX(${ // init off-screen for transition fx
|
|
1326
|
+
!notificationDiv.isRight ? '-' : '' }35px) ;`
|
|
1327
|
+
+ ( shadow ? `--shadow: -8px 13px 25px 0 ${ /\b(?:shadow|on)\b/i.test(shadow) ? 'gray' : shadow };
|
|
1328
|
+
box-shadow: var(--shadow) ; -webkit-box-shadow: var(--shadow) ; -moz-box-shadow: var(--shadow)`
|
|
1329
|
+
: '' ) + '}'
|
|
1330
|
+
+ `.notif-close-btn {
|
|
1331
|
+
cursor: pointer ; float: right ; position: relative ; right: -4px ; margin-left: -3px ;`
|
|
1309
1332
|
+ 'display: grid }' // top-align for non-OpenAI sites
|
|
1310
1333
|
+ '@keyframes notif-zoom-fade-out { 0% { opacity: 1 ; transform: scale(1) }' // transition out keyframes
|
|
1311
1334
|
+ '15% { opacity: 0.35 ; transform: rotateX(-27deg) scale(1.05) }'
|
|
@@ -1814,7 +1837,7 @@ const chatgpt = {
|
|
|
1814
1837
|
|
|
1815
1838
|
|
|
1816
1839
|
// Fix for blank background on dropdown elements
|
|
1817
|
-
if (element == 'dropdown') newElement.style.backgroundColor = 'var(--gray-900, rgb(32,
|
|
1840
|
+
if (element == 'dropdown') newElement.style.backgroundColor = 'var(--gray-900, rgb(32,33,35))';
|
|
1818
1841
|
|
|
1819
1842
|
this.elements.push(newElement);
|
|
1820
1843
|
this.activateObserver();
|
|
@@ -1843,15 +1866,15 @@ const chatgpt = {
|
|
|
1843
1866
|
},
|
|
1844
1867
|
|
|
1845
1868
|
async isLoaded(timeout = 5000) {
|
|
1846
|
-
await chatgpt.isLoaded()
|
|
1847
|
-
const timeoutPromise = new Promise(resolve => setTimeout(() =>
|
|
1869
|
+
await chatgpt.isLoaded()
|
|
1870
|
+
const timeoutPromise = new Promise(resolve => setTimeout(() => resolve(false), timeout))
|
|
1848
1871
|
const isLoadedPromise = new Promise(resolve => {
|
|
1849
|
-
if (chatgpt.getNewChatLink()) resolve(true)
|
|
1872
|
+
if (chatgpt.getNewChatLink()) resolve(true)
|
|
1850
1873
|
else new MutationObserver((_, obs) => {
|
|
1851
|
-
if (chatgpt.getNewChatLink()) { obs.disconnect(); resolve(true)
|
|
1852
|
-
}).observe(document.
|
|
1853
|
-
})
|
|
1854
|
-
return await Promise.race([isLoadedPromise, timeoutPromise])
|
|
1874
|
+
if (chatgpt.getNewChatLink()) { obs.disconnect() ; resolve(true) }
|
|
1875
|
+
}).observe(document.documentElement, { childList: true, subtree: true })
|
|
1876
|
+
})
|
|
1877
|
+
return await Promise.race([isLoadedPromise, timeoutPromise])
|
|
1855
1878
|
}
|
|
1856
1879
|
},
|
|
1857
1880
|
|
|
@@ -1869,31 +1892,31 @@ const chatgpt = {
|
|
|
1869
1892
|
return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest');
|
|
1870
1893
|
},
|
|
1871
1894
|
|
|
1872
|
-
speak(msg,
|
|
1873
|
-
//
|
|
1874
|
-
//
|
|
1875
|
-
//
|
|
1876
|
-
//
|
|
1877
|
-
|
|
1878
|
-
const { voice = 2, pitch = 2, speed = 1.1 } = options;
|
|
1895
|
+
speak(msg, { voice = 2, pitch = 2, speed = 1.1, onend } = {} ) {
|
|
1896
|
+
// Example call: chatgpt.speak(await chatgpt.getLastResponse(), { voice: 1, pitch: 2, speed: 3 })
|
|
1897
|
+
// - voice = index of voices available on user device
|
|
1898
|
+
// - pitch = float for pitch of speech from 0 to 2
|
|
1899
|
+
// - speed = float for rate of speech from 0.1 to 10
|
|
1900
|
+
// - onend = callback function invoked when speech finishes playing
|
|
1879
1901
|
|
|
1880
1902
|
// Validate args
|
|
1881
|
-
if (typeof msg
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
if (
|
|
1885
|
-
return console.error(`Invalid
|
|
1903
|
+
if (typeof msg != 'string') return console.error('Message must be a string!')
|
|
1904
|
+
const validOptionKeys = ['voice', 'pitch', 'speed', 'onend']
|
|
1905
|
+
for (const key in arguments[1]) {
|
|
1906
|
+
if (!validOptionKeys.includes(key))
|
|
1907
|
+
return console.error(`Invalid option '${key}'. Valid keys are: ${validOptionKeys}`)
|
|
1908
|
+
const val = arguments[1][key]
|
|
1909
|
+
if (key != 'onend' && typeof val != 'number' && !/^\d+$/.test(val))
|
|
1910
|
+
return console.error(`Invalid ${key} value '${val}'. Must be a number!`)
|
|
1911
|
+
else if (key == 'onend' && typeof val != 'function')
|
|
1912
|
+
return console.error(`Invalid ${key} value. Must be a function!`)
|
|
1886
1913
|
}
|
|
1887
1914
|
|
|
1888
|
-
try { // to speak msg
|
|
1889
|
-
const voices = speechSynthesis.getVoices()
|
|
1890
|
-
|
|
1891
|
-
utterance
|
|
1892
|
-
|
|
1893
|
-
utterance.pitch = pitch;
|
|
1894
|
-
utterance.rate = speed;
|
|
1895
|
-
speechSynthesis.speak(utterance);
|
|
1896
|
-
} catch (err) { console.error( err); }
|
|
1915
|
+
try { // to speak msg
|
|
1916
|
+
const utterance = new SpeechSynthesisUtterance(), voices = speechSynthesis.getVoices()
|
|
1917
|
+
Object.assign(utterance, { text: msg, voice: voices[voice], pitch: pitch, speed: speed, onend: onend })
|
|
1918
|
+
speechSynthesis.speak(utterance)
|
|
1919
|
+
} catch (err) { console.error(err) }
|
|
1897
1920
|
},
|
|
1898
1921
|
|
|
1899
1922
|
async summarize(text) {
|
|
@@ -2023,8 +2046,9 @@ const cjsFuncSynonyms = [
|
|
|
2023
2046
|
['render', 'parse'],
|
|
2024
2047
|
['reply', 'response'],
|
|
2025
2048
|
['sentiment', 'attitude', 'emotion', 'feeling', 'opinion', 'perception'],
|
|
2026
|
-
['speak', 'say', 'speech', 'talk', 'tts'],
|
|
2049
|
+
['speak', 'play', 'say', 'speech', 'talk', 'tts'],
|
|
2027
2050
|
['summarize', 'tldr'],
|
|
2051
|
+
['typing', 'generating'],
|
|
2028
2052
|
['unminify', 'beautify', 'prettify', 'prettyPrint']
|
|
2029
2053
|
];
|
|
2030
2054
|
const camelCaser = (words) => {
|