Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DuckDuckGPT safari #10

Open
Delamcode opened this issue Feb 19, 2023 · 78 comments
Open

DuckDuckGPT safari #10

Delamcode opened this issue Feb 19, 2023 · 78 comments

Comments

@Delamcode
Copy link

I know there is not official support, but using the userscripts extension I get this error: GM_getValue is not a function. (In 'GM_getValue("accessToken")', 'GM_getValue' is undefined). Do you have an idea of what is causing this? Here is the extension readme: https://github.com/quoid/userscripts

@adamlui
Copy link
Owner

adamlui commented Feb 19, 2023

Hey, I don't have a Mac so can't test support but can you try it using Tampermonkey @ https://www.tampermonkey.net/index.php?browser=safari&locale=en

@Delamcode
Copy link
Author

No, unfortunately I can’t. I was just wondering if it is something that would be easy to fix…

@adamlui
Copy link
Owner

adamlui commented Feb 19, 2023

How come? If you could it would probably work, GM_getValue is a function supported by userscript managers like Tampermonkey & Violentmonkey, the readme you linked is for a userscript editor only

@Delamcode
Copy link
Author

Because only userscripts supports ipad. It is not only an editor. Here is the popup in safari: https://github.com/quoid/userscripts#popup

@adamlui
Copy link
Owner

adamlui commented Feb 19, 2023

Ohh, well I asked da bot and it said:

image

Do you know how to edit the code? Can you remove line 17:

// @grant GM_getValue

Remove line 29:

var GM_getValue = (() => window.GM_getValue)()

And finally, replace line 168 with:

var accessToken = await localStorage.getItem("accessToken")

...and let me know if it works?

@Delamcode
Copy link
Author

Weird… the readme says it is supported but I’ll try and report back

@adamlui
Copy link
Owner

adamlui commented Feb 19, 2023

Ok then

@adamlui
Copy link
Owner

adamlui commented Feb 19, 2023

Actually you could try asking the extension author why the function wasn't supported on your iPad, and maybe provide them screenshots + link to my code

@Delamcode
Copy link
Author

Delamcode commented Feb 19, 2023

I now get this error:
undefined is not a function (near '...GM_xmlhttpRequest...')
asyncFunctionResume@[native code]
@[native code]
promiseReactionJobWithoutPromise@[native code]
appendChild@[native code]
injectJS@safari-web-extension://F0435466-F9A8-46C1-B498-8953D9410A63/content.js:274:34
processJS@safari-web-extension://F0435466-F9A8-46C1-B498-8953D9410A63/content.js:222:21
@safari-web-extension://F0435466-F9A8-46C1-B498-8953D9410A63/content.js:402:18

@Delamcode
Copy link
Author

Actually you could try asking the extension author why the function wasn't supported on your iPad, and maybe provide them screenshots + link to my code

Sure, I could try

@Delamcode
Copy link
Author

Is there any setup I’m missing?

@adamlui
Copy link
Owner

adamlui commented Feb 19, 2023

I now get this error: undefined is not a function (near '...GM_xmlhttpRequest...') asyncFunctionResume@[native code] @[native code] promiseReactionJobWithoutPromise@[native code] appendChild@[native code] injectJS@safari-web-extension://F0435466-F9A8-46C1-B498-8953D9410A63/content.js:274:34 processJS@safari-web-extension://F0435466-F9A8-46C1-B498-8953D9410A63/content.js:222:21 @safari-web-extension://F0435466-F9A8-46C1-B498-8953D9410A63/content.js:402:18

Yeah it looks like none of the GM_ functions are supported by that extension & DuckDuckGPT uses these 5:

// @grant GM_deleteValue
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_info
// @grant GM_xmlhttpRequest

@Delamcode
Copy link
Author

Interesting… I wonder why they don’t work as here it claims it’s supported…

@Delamcode
Copy link
Author

Could it be that userscripts uses GM.[Item] instead of GM_[Item]?

@Delamcode
Copy link
Author

Opened an issue on the extension ^^

@Delamcode
Copy link
Author

Maybe it has something to do with this?

@adamlui
Copy link
Owner

adamlui commented Feb 19, 2023

Maybe it has something to do with this?

I'ma look at it tonight after I sleep (I was up all night)

@Delamcode
Copy link
Author

According to the other issue I should change it to GM. but then I get this error (will edit if anything changes):
ReferenceError {} column: 43 line: 87 message: "Can't find variable: GM_registerMenuCommand" sourceURL: "https://duckduckgo.com/?q=what+is+the+meaning+of+life&t=ipad" stack: "enableCommandMenu@https://duckduckgo.com/?q=what+is+the+meaning+of+life&t=ipad:87:43↵main@https://duckduckgo.com/?q=what+is+the+meaning+of+life&t=ipad:54:26↵@https://duckduckgo.com/?q=what+is+the+meaning+of+life&t=ipad:112:17↵@https://duckduckgo.com/?q=what+is+the+meaning+of+life&t=ipad:179:3↵@https://duckduckgo.com/?q=what+is+the+meaning+of+life&t=ipad:181:15↵global code@https://duckduckgo.com/?q=what+is+the+meaning+of+life&t=ipad:182:11↵appendChild@[native code]↵injectJS@safari-web-extension://F0435466-F9A8-46C1-B498-8953D9410A63/content.js:274:34↵processJS@safari-web-extension://F0435466-F9A8-46C1-B498-8953D9410A63/content.js:222:21↵@safari-web-extension://F0435466-F9A8-46C1-B498-8953D9410A63/content.js:402:18" __proto__: Object

@quoid
Copy link

quoid commented Feb 19, 2023

I am one of the maintainers of the previously mentioned user script manager. The reason an error is thrown is because synchronous GM_ apis are not supported by the manager (outside of GM_info and GM_xmlhttpRequest). Only certain async counter parts are supported - readme. The main difference in these api methods being sync vs async.

I recommend the newer API methods, but thats obviously up to the user script author. If you'd like to support the newer API methods you could do something like:

...
// @grant            GM_deleteValue
// @grant            GM_getValue
// @grant            GM_setValue
// @grant            GM_info
// @grant            GM_xmlhttpRequest
// @grant            GM.deleteValue
// @grant            GM.getValue
// @grant            GM.setValue
// @grant            GM.info
// @grant            GM.xmlHttpRequest
...
var GM_setValue = (() => window.GM_setValue ?? GM.setValue)()
var GM_deleteValue = (() => window.GM_deleteValue ?? GM.deleteValue)()
var GM_info = (() => window.GM_info ?? GM.info)()
var GM_xmlhttpRequest = (() => window.GM_xmlhttpRequest ?? GM.xmlHttpRequest)()
var GM_getValue = (() => window.GM_getValue ?? GM.getValue)()
...

@Delamcode
Copy link
Author

Using just these updates makes it “work” but asks to log in even though I’m logged in…

@adamlui
Copy link
Owner

adamlui commented Feb 21, 2023

@Delamcode did you revert the edits in #10 (comment) before applying @quoid's tweak? If so, I asked da bot and apparently the "nullish coalescing operator (??), which is a relatively new feature introduced in ECMAScript 2020 [is not always supported]. Unfortunately, not all browsers support this feature yet, including some versions of Safari on iPad."

Can you try replacing them with the OR operator?

var GM_setValue = (() => window.GM_setValue || GM.setValue)()
var GM_setValue = (() => window.GM_setValue || GM.setValue)()
var GM_deleteValue = (() => window.GM_deleteValue || GM.deleteValue)()
var GM_info = (() => window.GM_info || GM.info)()
var GM_xmlhttpRequest = (() => window.GM_xmlhttpRequest || GM.xmlHttpRequest)()
var GM_getValue = (() => window.GM_getValue || GM.getValue)()

Also what version of Safari are you using, is it 10+?

@Delamcode
Copy link
Author

I am using safari 15. Yes, I did revert. I will try this.

@Delamcode
Copy link
Author

Now both methods stopped working… (Waiting for Response) with this error: JSON Parse error: Unrecognized token '<'
onload@
@safari-web-extension://ED32EE2A-2F54-40AF-89E4-E1F764226C05/content.js:180:38
asyncFunctionResume@[native code]
@safari-web-extension://ED32EE2A-2F54-40AF-89E4-E1F764226C05/content.js:156:59

@adamlui
Copy link
Owner

adamlui commented Feb 21, 2023

Actually I just found out ChatGPT's been down forever...
image
So can you go back to using the ??'s, I think it might work when they're back up

@Delamcode
Copy link
Author

The actual website is working fine for me, and I am logged in. Using ?? I still get the log in @ error, even though I’m logged in…

@Delamcode
Copy link
Author

Is it possible to console.log the id on my computer, and then hard code it on my ipad script?

@adamlui
Copy link
Owner

adamlui commented Feb 21, 2023

Is it possible to console.log the id on my computer, and then hard code it on my ipad script?

Probably, also you could try adding 'GM_deleteValue("accessToken")' after line 27, save, refresh search page, then remove the line, re-save, then refresh search page (just to clear it out)

@Delamcode
Copy link
Author

Where (and how) would you recommend doing the console.log?

@adamlui
Copy link
Owner

adamlui commented Feb 21, 2023

Can you try clearing the access token first see if that works? (I had to do this in incompatible browsers & it worked is why I didn't include them)

@Delamcode
Copy link
Author

Sure I might look into it if I have time!

@quoid
Copy link

quoid commented Feb 22, 2023

Now I get this error again: JSON Parse error: Unrecognized token '<' ...
that means you are getting a HTML response like 404 or 500 error...
How much are iPads? I think I need to buy one to make it work ...

This is happening on macOS as well, not just iPadOS/iOS.

You can just log the response in GM_xmlhttpRequest, like so:

...
onload: function(response) {
    console.log('r', response)
    ...
}
...

It's a 403 error, I pasted the response below:

{
    readyState: 4
    response: "<html>↵  <head>↵    <style global>body{font-family:Arial,Helvetica,sans-serif}.container{align-items:center;display:flex;flex-direction:colu…"
    responseHeaders: "alt-svc: h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400\r↵cache-control: private, max-age=0, no-store, no-cache, must-revalidate, post-check=0…"
    responseText: "<html>↵  <head>↵    <style global>body{font-family:Arial,Helvetica,sans-serif}.container{align-items:center;display:flex;flex-direction:colu…"
    responseType: ""
    responseURL: "https://chat.openai.com/api/auth/session"
    status: 403
    statusText: "Forbidden"
    timeout: 0
}

If you add a check for that here:

if (isBlockedbyCloudflare(response.responseText) || response.status === 403) {
   alertLogin(); return 
}

The 403 error will go away, but it looks like the subsequent 200 responses are returning an empty object, pasted below:

{
    readyState: 4
    response: "{}"
    responseHeaders: "alt-svc: h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400\r↵cf-cache-status: DYNAMIC\r↵cf-ray: 79d39c8a29d5e6e4-EWR\r↵content-length: 2…"
    responseText: "{}"
    responseType: ""
    responseURL: "https://chat.openai.com/api/auth/session"
    status: 200
    statusText: "OK"
    timeout: 0
    withCredentials: false
}

I am not entirely sure how this user script is supposed to function, but it seems you are expecting an access token from that response. I am not sure the context where the request is run has access to that token. I believe it's akin to making the request in an incognito tab, so I am not sure how one would get the actual token.

I am not sure how to work around this.

@adamlui
Copy link
Owner

adamlui commented Feb 22, 2023

Hey @quoid the userscript forces user to visit login page if:

  1. POST request to https://chat.openai.com/backend-api/conversation is unauthorized (line 125)
  2. Access token expired (line 135)
  3. Cloudflare firewall kicked in (line 175) (so even if logged in, human can pass the check at least)

In Windows browsers when these 3 conditions do not exist, https://chat.openai.com/api/auth/session returns the following object:

{"user":{"id":"user-9K0mEpF8oO9P6LsbYlV30ka6","name":"[email protected]","email":"[email protected]","image":"https://s.gravatar.com/avatar/3f6928f37e3fe9e016fed71c8c495608?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fad.png","picture":"https://s.gravatar.com/avatar/3f6928f37e3fe9e016fed71c8c495608?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fad.png","groups":[]},"expires":"2023-03-24T03:35:48.253Z","accessToken":"_______"}

Without the 'accessToken' value from this expected object, requests to https://chat.openai.com/backend-api/conversation (line 196) fail to generate a chat response. So based on your discovery, Apple browser is treating it like incognito & I don't know why :(

When I researched the 1st error earlier, I came across this answer: https://stackoverflow.com/a/59216403/2512339

... led to this error on the iOS device emulator but not the Android device emulator. . Apple and Windows use different line endings, which is important considering template literals allow multiline strings

Although no template literals are used, the answer does indicate something is different w/ how Apple handles requests (if that's of any help)

@ACTCD
Copy link

ACTCD commented Feb 24, 2023

@adamlui This has nothing to do with browsers or extensions.

Your script will only work in certain "normal" situations because it lacks the necessary judgment (or error handling).

For example you could check http-status, content-type... When the xhr request does not return a json type, you cannot use JSON.parse to process the content.

Your isBlockedbyCloudflare func is both unnecessary and very inaccurate, on a 403 or not 200 status, you won't get "Just a moment..." every time.

If these code is not gpt's work, perhaps you can let it tell you how to write it. (forgive my joke :D)

@adamlui
Copy link
Owner

adamlui commented Feb 24, 2023

@adamlui This has nothing to do with browsers or extensions. Your script will only work in certain "normal" situations...

And what is abnormal to you? (not sure why the quotes)

...because it lacks the necessary judgment (or error handling)

getAnswer() literally leads w/ a try-catch...

For example you could check http-status, content-type... When the xhr request does not return a json type, you cannot use JSON.parse to process the content.

JSON.parse in your linked getAccessToken() is in aforementioned error handling, so it doesn't matter if it's not json type (script will go to catch & clear token, then force user to login)

Your isBlockedbyCloudflare func is both unnecessary and very inaccurate

"Just a moment..." is the only situation where user is blocked by Cloudflare, so it is in fact very accurate. Why is it "unnecessary" for user to then be forced to clear Cloudflare checks? Have you ever used ChatGPT? (It doesn't work w/o passing it)

...on a 403 or not 200 status, you won't get "Just a moment..." every time.

Of course. Who said isBlockedbyCloudflare is for 403 or not-200 statuses? It's specifically for Cloudflare (it's literally in the name dude). If some other not-200 status shows, again, catch block of getAnswer() clears token & forces login (Cloudflare checks don't need to lose token)

If these code is not gpt's work, perhaps you can let it tell you how to write it. (forgive my joke :D)

No offense is taken, it works in every browser except Safari, why not put your money where your mouth is & create a commit?

@adamlui
Copy link
Owner

adamlui commented Feb 24, 2023

@ACTCD Surely the big game you talk means you can fix it in 5 minutes max. So don't be scared now, back your mouth up 😉 (or no one will believe you)

@quoid
Copy link

quoid commented Feb 24, 2023

@adamlui

So based on your discovery, Apple browser is treating it like incognito & I don't know why :(

I should have been more clear. I got the userscript to pretty much work in Chrome/Violentmonkey on macOS. The issue I was seeing was specific to the Safari and even more specifically the background script of an extension.

If I visit https://chat.openai.com/api/auth/session from a normal tab, I can see the token (expect response). But if I fetch that token from the background script it is an empty object 🤷

My guess is that the background script context is a completely isolated world in Safari, so it is treated like an incognito tab.

@ACTCD

This has nothing to do with browsers or extensions.

Speaking on the issue @Delamcode brings up, I am not entirely sure that is true. I can not be 100% sure because I only did some cursory exploration of the issue, but I think it has to do with the fact that background pages are an isolated environment.

However, I do think that this is generally a good thing. I do not like the idea of background scripts being able to read auth tokens from users, for that I am not sure I would classify this as a bug, but perhaps a feature.

I am curious how ViolentMonkey seems to accomplish this...

Again, I would like to repeat that I did some hasty investigation so everything I say might not be accurate.

@adamlui
Copy link
Owner

adamlui commented Feb 24, 2023

I should have been more clear. I got the userscript to pretty much work in Chrome/Violentmonkey on macOS. The issue I was seeing was specific to the Safari and even more specifically the background script of an extension.

Actually I said "Apple browser" but meant Safari & totally got what you meant!

Based on your detailed clarification though, I found a few posts of Safari WebExtensions' background requests always failing but not in Chrome (just as you described, so you are onto something):

@Delamcode
Copy link
Author

Delamcode commented Feb 25, 2023

So based on your discovery, Apple browser is treating it like incognito & I don't know why :(

I should have been more clear. I got the userscript to pretty much work in Chrome/Violentmonkey on macOS. The issue I was seeing was specific to the Safari and even more specifically the background script of an extension.

If I visit https://chat.openai.com/api/auth/session from a normal tab, I can see the token (expect response). But if I fetch that token from the background script it is an empty object 🤷

My guess is that the background script context is a completely isolated world in Safari, so it is treated like an incognito tab.

Which is weird, because I have even tried disabling all privacy settings in safari and this is still happening… Could it be that extensions cannot communicate with other sites other than the one that is being used? Apple does after all sandbox apps on ios…

@quoid
Copy link

quoid commented Feb 25, 2023

Could it be that extensions cannot communicate with other sites other than the one that is being used? Apple does after all sandbox apps on ios…

@Delamcode I don't think that is it. You can fetch data from other APIs/sites without issue (example pasted below). I think it is just that the background page is isolated. The call https://chat.openai.com/api/auth/session is successful but it doesn't return the token because as far as it knows, you are not logged.

// ==UserScript==
// @name        Example API call
// @description Example API call
// @match       *://*.example.com/*
// @grant       GM.xmlHttpRequest
// ==/UserScript==

(async () => {
    GM.xmlHttpRequest({
        method: "GET",
        url: "https://jsonplaceholder.typicode.com/posts",
        onloadend: e => {
            let response = e.response;
            try {
                response = JSON.parse(response);
            } catch (error) {
                console.error("Failed to parse JSON");
            }
            console.log(response);
        }
    });
})();

@adamlui
Copy link
Owner

adamlui commented Mar 30, 2023

@Delamcode can you try installing the latest version @ https://greasyfork.org/en/scripts/459849-duckduckgpt and turn on Proxy Mode:

image

With this activated, requests are sent thru proxy using my own key so it should work

@Delamcode
Copy link
Author

Delamcode commented Mar 31, 2023 via email

@adamlui
Copy link
Owner

adamlui commented Mar 31, 2023

@Delamcode Can you check safari console? Does an error like 'GM_registerMenuCommand is not recognized' appear? If so I'm going to work on removing the menu and hard-code the proxy

@Delamcode
Copy link
Author

Delamcode commented Mar 31, 2023 via email

@adamlui
Copy link
Owner

adamlui commented Mar 31, 2023

@Delamcode Oh I changed it to // @match https://duckduckgo.com/?* so it only appears on search results pages. But I just checked Safari Userscripts doesn't support menus, but I'm curious, what happens when you type a search?

adamlui added a commit that referenced this issue Mar 31, 2023
@adamlui
Copy link
Owner

adamlui commented Mar 31, 2023

@Delamcode
Copy link
Author

Delamcode commented Mar 31, 2023 via email

@adamlui
Copy link
Owner

adamlui commented Mar 31, 2023

@Delamcode GM_registerMenuCommand was removed from the updated script, so this error is coming from the old one (which always worked and showed on search results pages, just not on duckduckgo.com)

Can you try disabling this old script and install/enable the new one? (duckduckgpt-ios.user.js)

@Delamcode
Copy link
Author

Delamcode commented Apr 1, 2023 via email

@adamlui
Copy link
Owner

adamlui commented Apr 1, 2023

@Delamcode what's the console showing for it?

@Delamcode
Copy link
Author

Delamcode commented Apr 1, 2023 via email

@adamlui
Copy link
Owner

adamlui commented Apr 1, 2023

@Delamcode I figured it out, the proxy I was using was limited to my own IP but I fixed it in this update: https://github.com/kudoai/duckduckgpt/raw/main/greasemonkey/duckduckgpt-ios.user.js can you pls try?

@Delamcode
Copy link
Author

Delamcode commented Apr 1, 2023 via email

adamlui added a commit that referenced this issue Apr 24, 2023
adamlui added a commit that referenced this issue May 24, 2023
Made CSS More Readable ↞ [auto-sync from `kudoai/duckduckgpt`]
adamlui added a commit that referenced this issue Nov 3, 2023
- Removed `()` around unmodded param of `updateCheck()`'s `GM.xmlHttpRequest({onload})` ↞ [auto-sync from `adamlui/chatgpt-auto-continue`]
@adamlui
Copy link
Owner

adamlui commented Dec 19, 2023

Hey @Delamcode it works on Android now via Kiwi or Firefox which supports Tampermonkey, can you try intsalling Firefox for iOS then Tampermonkey for Firefox and confirm it works on iOS now too?

@Delamcode
Copy link
Author

Delamcode commented Dec 28, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants