KudoAI / chatgpt.js

🤖 A powerful, open source client-side JavaScript library for ChatGPT
https://chatgpt.js.org
MIT License
1.91k stars 142 forks source link

Add access token management #83

Closed adamlui closed 1 year ago

adamlui commented 1 year ago
          also (this is just an idea of mine), I think we should store an access token somewhere in the chatgpt object as a variable, and update it once it expires (the token has an expiration date, reference [here](https://github.com/kudoai/chatgpt.js/blob/main/chatgpt.js#L379)) to avoid getting rate limited by the api and reducing the speed of the library

problem is idk about the security of doing this

edit: it shouldn't even matter since there's literally a function that retrieves the access token, so storing it in the object is not even a big deal, and removing the object from the window will literally make it disappear

Originally posted by @madkarmaa in https://github.com/kudoai/chatgpt.js/issues/79#issuecomment-1634781262

madkarmaa commented 1 year ago

what do you think

adamlui commented 1 year ago

Yes it can be stored using local storage, then I have to update docs to require that permission for platforms like chrome

adamlui commented 1 year ago

I just woke up and just worked on your awesome getResponseFromAPI without eating, so I have to eat first though (then I'ma rename getResponse to getResponseFromDOM, then re-add getResponse using conditional logic)

You could get started on editing getAccessToken if you want, you could look at DDGPT/bravegpt to see how storage is implemented

madkarmaa commented 1 year ago

isn't localStorage too easy to access? also, it is permanent (until removed by the user). I know it's easy to get the access token, but that'll literally store it globally and it'll become avaiable for whatever extension or userscript or javascript injection that interacts with the website

adamlui commented 1 year ago

Yes it is permanent which is fine if getAccessToken is edited to return stored value and on errors in methods that call it replaces it (like my webgpt scripts do)

Re global access it doesn't matter, if the key is named openAIaccessToken and some other app relies on storage for a key with this name, it will not break and we are doing them a favor by populating it already

adamlui commented 1 year ago

This is how I refresh key when rate limit is reached for a proxy API in ddgpt:

  if (event.responseText.includes('finish_reason')) { // if AIGCF error encountered
      GM_setValue('aigcfKey', false) // clear GM key for fresh getAIGCFkey()

      // Determine index of AIGCF in endpoint map
      let aigcfMapIndex = -1
      for (let i = 0 ; i < proxyEndpointMap.length ; i++) {
          const endpoint = proxyEndpointMap[i]
          if (endpoint.some(item => item.includes('aigcfun'))) {
              aigcfMapIndex = i ; break
      }}

      // Updated AIGCF endpoint w/ fresh key (using fresh IP)
      (async () => { // IIFE to use await
          proxyEndpointMap[aigcfMapIndex][0] = (
              'https://api.aigcfun.com/api/v1/text?key=' + await getAIGCFkey())
          getShowReply(messages, callback) // re-fetch reply
      })()

..and the getAIGCFkey is:

    function getAIGCFkey() {
        return new Promise((resolve) => {
            const publicKey = GM_getValue('aigcfKey')
            if (!publicKey) {         
                GM.xmlHttpRequest({ method: 'GET', url: 'https://api.aigcfun.com/fc/key',
                    headers: {
                        'Content-Type': 'application/json',
                        'Referer': 'https://aigcfun.com/',
                        'X-Forwarded-For': chatgpt.generateRandomIP() },
                    onload: (response) => {
                        const newPublicKey = JSON.parse(response.responseText).data
                        if (!newPublicKey) { ddgptConsole.error('Failed to get AIGCFun public key') ; return }
                        GM_setValue('aigcfKey', newPublicKey)
                        console.info('AIGCFun public key set: ' + newPublicKey)
                        resolve(newPublicKey)
                }})
            } else resolve(publicKey)
    })}

(so something similar can be implemented for openai token)

adamlui commented 1 year ago

(and the GM methods can be replaced with JS equivalents)

adamlui commented 1 year ago

@madkarmaa actually in hindsight your storing it in chatgpt obj is better since user won't need additional permissions, so stores like Chrome will approve more leniently!

adamlui commented 1 year ago

This is an example of how hasty they are to reject even established extensions that are Featured from Verified publishers:

image

adamlui commented 1 year ago

I clapped back with a Karen email and got them to apologize though 😂

image

adamlui commented 1 year ago

This the karen email I sent to get the apology:

The reviewer falsely accuses me of "mimicking ranking" for including a badge on tiles that ChatGPT Widescreen received #2 Product of the Week on Product Hunt.

However, it is not "mimicking" if it factually occurred.

Here is the email received confirming this ranking: https://imgur.com/lyZh6La

Also, if you go to https://www.producthunt.com/products/chatgpt-widescreen-mode/awards, you will note it clearly says "1 Badges" (you don't get that awarded if you didn't rank in top 5)

The corrective action demanded of me by this reviewer is to "Remove the content that is mimicking ranking," however this statement in itself is inaccurate as no mimicry is occurring. The badge is provided by Product Hunt, clearly showing Product Hunt logo, and I am using it as intended in a 100% honest manner. Please remove this violation from my account as I am a man of great honor.

madkarmaa commented 1 year ago

bruh 💀

adamlui commented 1 year ago

One with honor must fight for honor (one without is justifiably rejected)

madkarmaa commented 1 year ago

@madkarmaa actually in hindsight your storing it in chatgpt obj is better since user won't need additional permissions, so stores like Chrome will approve more leniently!

there we go, PR #84