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