|
3 | 3 | // @description Add AI chat & product/category summaries to Amazon shopping, powered by the latest LLMs like GPT-4o!
|
4 | 4 | // @author KudoAI
|
5 | 5 | // @namespace https://kudoai.com
|
6 |
| -// @version 2025.5.14 |
| 6 | +// @version 2025.5.14.1 |
7 | 7 | // @license MIT
|
8 | 8 | // @icon https://amazongpt.kudoai.com/assets/images/icons/app/black-gold-teal/icon48.png?v=8e8ed1c
|
9 | 9 | // @icon64 https://amazongpt.kudoai.com/assets/images/icons/app/black-gold-teal/icon64.png?v=8e8ed1c
|
|
139 | 139 | latestResourceCommitHash: '78db856' // for cached <app|messages>.json
|
140 | 140 | }
|
141 | 141 | app.urls = { resourceHost: `https://cdn.jsdelivr.net/gh/KudoAI/amazongpt@${app.latestResourceCommitHash}` }
|
142 |
| - const remoteAppData = await new Promise(resolve => xhr({ |
143 |
| - method: 'GET', url: `${app.urls.resourceHost}/assets/data/app.json`, |
144 |
| - onload: resp => resolve(JSON.parse(resp.responseText)) |
145 |
| - })) |
146 |
| - Object.assign(app, { ...remoteAppData, urls: { ...app.urls, ...remoteAppData.urls }}) |
147 |
| - app.msgs = { |
148 |
| - appDesc: 'Add AI to Amazon shopping', |
149 |
| - menuLabel_proxyAPImode: 'Proxy API Mode', |
150 |
| - menuLabel_preferred: 'Preferred', |
151 |
| - menuLabel_autoFocusChatbar: 'Auto-Focus Chatbar', |
152 |
| - menuLabel_whenStreaming: 'when streaming', |
153 |
| - menuLabel_background: 'Background', |
154 |
| - menuLabel_foreground: 'Foreground', |
155 |
| - menuLabel_animations: 'Animations', |
156 |
| - menuLabel_replyLanguage: 'Reply Language', |
157 |
| - menuLabel_colorScheme: 'Color Scheme', |
158 |
| - menuLabel_auto: 'Auto', |
159 |
| - menuLabel_about: 'About', |
160 |
| - menuLabel_settings: 'Settings', |
161 |
| - menuLabel_random: 'Random', |
162 |
| - menuLabel_saved: 'Saved', |
163 |
| - componentLabel_used: 'used', |
164 |
| - about_author: 'Author', |
165 |
| - about_and: '&', |
166 |
| - about_contributors: 'contributors', |
167 |
| - about_version: 'Version', |
168 |
| - about_poweredBy: 'Powered by', |
169 |
| - about_openSourceCode: 'Open source code', |
170 |
| - about_latestChanges: 'Latest changes', |
171 |
| - scheme_light: 'Light', |
172 |
| - scheme_dark: 'Dark', |
173 |
| - mode_proxy: 'Proxy Mode', |
174 |
| - mode_streaming: 'Streaming Mode', |
175 |
| - mode_autoScroll: 'Auto-Scroll', |
176 |
| - mode_debug: 'Debug Mode', |
177 |
| - tooltip_fontSize: 'Font size', |
178 |
| - tooltip_sendReply: 'Send reply', |
179 |
| - tooltip_askRandQuestion: 'Ask random question', |
180 |
| - tooltip_minimize: 'Minimize', |
181 |
| - tooltip_restore: 'Restore', |
182 |
| - tooltip_expand: 'Expand', |
183 |
| - tooltip_shrink: 'Shrink', |
184 |
| - tooltip_close: 'Close', |
185 |
| - tooltip_copy: 'Copy', |
186 |
| - tooltip_generate: 'Generate', |
187 |
| - tooltip_generating: 'Generating', |
188 |
| - tooltip_regenerate: 'Regenerate', |
189 |
| - tooltip_regenerating: 'Regenerating', |
190 |
| - tooltip_play: 'Play', |
191 |
| - tooltip_playing: 'Playing', |
192 |
| - tooltip_page: 'Page', |
193 |
| - tooltip_reply: 'Reply', |
194 |
| - tooltip_code: 'Code', |
195 |
| - tooltip_generatingAudio: 'Generating audio', |
196 |
| - helptip_proxyAPImode: 'Uses a Proxy API for no-login access to AI', |
197 |
| - helptip_preferredAPI: 'API to use when getting answers in Proxy Mode', |
198 |
| - helptip_streamingMode: 'Receive replies in a continuous text stream', |
199 |
| - helptip_autoFocusChatbar: 'Auto-focus chatbar whenever it appears', |
200 |
| - helptip_autoScroll: 'Auto-scroll responses as they generate in Streaming Mode', |
201 |
| - helptip_bgAnimations: 'Show animated backgrounds in UI components', |
202 |
| - helptip_fgAnimations: 'Show foreground animations in UI components', |
203 |
| - helptip_replyLanguage: 'Language for AmazonGPT to reply in', |
204 |
| - helptip_colorScheme: 'Scheme to display AmazonGPT UI components in', |
205 |
| - helptip_debugMode: 'Show detailed logging in browser console', |
206 |
| - placeholder_typeSomething: 'Type something', |
207 |
| - prompt_updateReplyLang: 'Update reply language', |
208 |
| - alert_langUpdated: 'Language updated', |
209 |
| - alert_willReplyIn: 'will reply in', |
210 |
| - alert_yourSysLang: 'your system language', |
211 |
| - alert_choosePlatform: 'Choose a platform', |
212 |
| - alert_updateAvail: 'Update available', |
213 |
| - alert_newerVer: 'An update to', |
214 |
| - alert_isAvail: 'is available', |
215 |
| - alert_upToDate: 'Up-to-date', |
216 |
| - alert_isUpToDate: 'is up-to-date', |
217 |
| - alert_unavailable: 'unavailable', |
218 |
| - alert_isOnlyAvailFor: 'is only available for', |
219 |
| - alert_userscriptMgrNoStream: 'Your userscript manager does not support returning stream responses', |
220 |
| - alert_isCurrentlyOnlyAvailBy: 'is currently only available by', |
221 |
| - alert_openAIsupportSoon: 'Support for OpenAI API will be added shortly', |
222 |
| - alert_waitingFor: 'Waiting for', |
223 |
| - alert_response: 'response', |
224 |
| - alert_login: 'Please login', |
225 |
| - alert_thenRefreshPage: 'then refresh this page', |
226 |
| - alert_tooManyRequests: 'ChatGPT is flooded with too many requests', |
227 |
| - alert_parseFailed: 'Failed to parse response JSON', |
228 |
| - alert_checkCloudflare: 'Please pass Cloudflare security check', |
229 |
| - alert_notWorking: 'is not working', |
230 |
| - alert_ifIssuePersists: 'If issue persists', |
231 |
| - alert_try: 'Try', |
232 |
| - alert_switchingOn: 'switching on', |
233 |
| - alert_switchingOff: 'switching off', |
234 |
| - alert_selectingDiff: 'selecting a different', |
235 |
| - alert_generated: 'Generated', |
236 |
| - notif_copiedToClipboard: 'Copied to clipboard', |
237 |
| - notif_downloaded: 'downloaded', |
238 |
| - btnLabel_moreAIextensions: 'More AI Extensions', |
239 |
| - btnLabel_rateUs: 'Rate Us', |
240 |
| - btnLabel_discuss: 'Discuss', |
241 |
| - btnLabel_getSupport: 'Get Support', |
242 |
| - btnLabel_checkForUpdates: 'Check for Updates', |
243 |
| - btnLabel_update: 'Update', |
244 |
| - btnLabel_dismiss: 'Dismiss', |
245 |
| - btnLabel_visitPage: 'Visit Page', |
246 |
| - btnLabel_download: 'Download', |
247 |
| - btnLabel_convo: 'chat', |
248 |
| - link_viewChanges: 'View changes', |
249 |
| - state_on: 'On', |
250 |
| - state_off: 'Off', |
251 |
| - state_no: 'No' |
| 142 | + const remoteData = { |
| 143 | + app: await new Promise(resolve => xhr({ |
| 144 | + method: 'GET', url: `${app.urls.resourceHost}/assets/data/app.json`, |
| 145 | + onload: resp => resolve(JSON.parse(resp.responseText)) |
| 146 | + })), |
| 147 | + msgs: await new Promise(resolve => { |
| 148 | + const msgHostDir = app.urls.resourceHost + '/greasemonkey/_locales/', |
| 149 | + msgLocaleDir = ( env.browser.language ? env.browser.language.replace('-', '_') : 'en' ) + '/' |
| 150 | + let msgHref = msgHostDir + msgLocaleDir + 'messages.json', msgXHRtries = 0 |
| 151 | + function fetchMsgs() { xhr({ method: 'GET', url: msgHref, onload: handleMsgs })} |
| 152 | + function handleMsgs(resp) { |
| 153 | + try { // to return localized messages.json |
| 154 | + const msgs = JSON.parse(resp.responseText), flatMsgs = {} |
| 155 | + for (const key in msgs) // remove need to ref nested keys |
| 156 | + if (typeof msgs[key] == 'object' && 'message' in msgs[key]) |
| 157 | + flatMsgs[key] = msgs[key].message |
| 158 | + resolve(flatMsgs) |
| 159 | + } catch (err) { // if bad response |
| 160 | + msgXHRtries++ ; if (msgXHRtries == 3) return resolve({}) // try original/region-stripped/EN only |
| 161 | + msgHref = env.browser.language.includes('-') && msgXHRtries == 1 ? // if regional lang on 1st try... |
| 162 | + msgHref.replace(/(_locales\/[^_]+)_[^_]+(\/)/, '$1$2') // ...strip region before retrying |
| 163 | + : ( msgHostDir + 'en/messages.json' ) // else use default English messages |
| 164 | + fetchMsgs() |
| 165 | + } |
| 166 | + } |
| 167 | + fetchMsgs() |
| 168 | + }) |
252 | 169 | }
|
| 170 | + Object.assign(app, { ...remoteData.app, urls: { ...app.urls, ...remoteData.app.urls }, msgs: remoteData.msgs }) |
253 | 171 |
|
254 | 172 | // Init API data
|
255 | 173 | const apis = Object.assign(Object.create(null), await new Promise(resolve => xhr({
|
|
0 commit comments