Blog Series: #1 ChatGPT + BetterTouchTool = ❤️

Great ideas!

You can use the "Custom Context Menu (New)" action, that gives you much more control over execution than the "conflict menu".

I think I'll also add some dedicated ChatGPT actions given the usefulness of all this.

2 Likes

Thanks @Andreas_Hegenberg & good morning :sunny:

I've used the "Custom Context Menu (New)" action, but don't know how I can get the value of the context menu item that was clicked on by the user, so that I can insert this value into the JavaScript that the Named Trigger runs?

Is it possible to get the value of the custom context menu that a user clicked on?

There are multiple ways, the easiest would probably be to use the "Assign Variable" action

Then in the Java Script get the variable via
let result = await callBTT('get_string_variable', {variable_name:'ChatGPTOperation'})

1 Like

Here is a quick and dirty fix for the issue with the 'return' key not working properly in the BTT webview.
In the advanced settings of the floating webview in BTT, paste this user script :

const textarea = document.querySelector('textarea');
const button = document.querySelector('button.absolute.p-1.rounded-md.text-gray-500');

textarea.addEventListener('keydown', function(event) {
  if (event.keyCode === 13) {
    event.preventDefault();
    button.click();
  }
});

Haven't seen any issue so far with this.

1 Like

Thanks! It works!

Edit: Actually, when I change chats, it doesn't work anymore

Maybe adding the event listener to document would work better:

document.addEventListener('keydown', function(event) {
  if (event.keyCode === 13) {
    const button = document.querySelector('button.absolute.p-1.rounded-md.text-gray-500');
    event.preventDefault();
    button.click();
  }
});

Yep, it does work!

Here is a better version so that Shift+Enter makes a new line :

const keys = {};

document.addEventListener('keydown', function(event) {

  keys[event.key] = true;

  if (keys['Enter'] && !keys['Shift']) {
    event.preventDefault();
    const button = document.querySelector('button.absolute.p-1.rounded-md.text-gray-500');
    button.click();
  }
});

document.addEventListener("keyup", function(event) {
  delete keys[event.key];
});

EDIT:
And here the ChatGPT optimized script :wink:

ChatGPT

Here's an optimized version of the code:

const keys = new Set(); // Use a set for better performance

document.addEventListener('keydown', (event) => {
  keys.add(event.key); // Add key to set

  if (keys.has('Enter') && !keys.has('Shift')) { // Check if both keys are in the set
    const button = document.querySelector('button.absolute.p-1.rounded-md.text-gray-500');
    event.preventDefault();
    button.click();
  }
});

document.addEventListener("keyup", (event) => {
  keys.delete(event.key); // Remove key from set
});

The changes made were the following:

  1. Use Set instead of {} for the keys variable - this provides better performance when checking for the existence of elements in a collection.

  2. Use arrow functions instead of anonymous functions - this simplifies the code and makes it easier to read.

  3. Use add instead of assignment to add a key to the set - this is more explicit and helps to avoid accidentally overwriting the set.

  4. Use has instead of [] to check for the existence of keys in the set - this is clearer and again helps to avoid accidentally overwriting the set.

  5. Use delete instead of delete on an object to remove a key from the set - this is more consistent with using a Set.

2 Likes

For some reason, when I attempt to use the implemented Inline ChatGPT, I'm getting an "Error" response from the API.

I'm not using the paid service. Just the free service, but it includes a small amount of credits each month so I presume it should still work, yes?

unfortunately I don't have experience with the free accounts.

With the new alpha I'd recommend trying the new "Transform & replace selection with ChatGPT",BTT includes some free tokens for users with an active license

2 Likes

I am trying the new alpha and it's fantastic, thanks for your work as always. Will there be a way to get a "dynamic user prompt", so that we can tell ChatGPT what to do with the provided text time by time?

yes that will be added very soon
(for now you can leave the user prompt empty, then it will do whatever you write & select before triggering the action)

1 Like

Is it possible, with BTT, to show the response of ChatGTP in a floating window or something like that (and copying it automatically), instead of replacing the selected text? It would open up a lot of possibilities (for example the user could select some text and visualize a translation or some insights about it).

Secondarily, is it possibile for BTT to read the content of a webpage? If this is possible, it would allow to create a sort of browser-agnostic web assistant in the style of Microsoft Edge with the new Bing.

In addition to these questions, I would like to point out that in the BTT test version it is not possible to save the changes of the "Transform & Replace Selection With ChatGPT" action when the change is not in the text but in the value of the "Number of previous requests to include" parameter.

You can do that with the "Floating HTML Action", here is an example. Requires BTT 4.062:

<html>
  <style>
    body {
       background:white;
    }
    // spinner from https://loading.io/css/
    .lds-dual-ring {
      display: inline-block;
      width: 80px;
      height: 80px;
    }
    .lds-dual-ring:after {
      content: " ";
      display: block;
      width: 64px;
      height: 64px;
      margin: 8px;
      border-radius: 50%;
      border: 6px solid #fff;
      border-color: #fff transparent #fff transparent;
      animation: lds-dual-ring 1.2s linear infinite;
    }
    @keyframes lds-dual-ring {
      0% {
        transform: rotate(0deg);
      }
      100% {
        transform: rotate(360deg);
      }
    }
  </style>
  <script>
    async function chatGPTRequest(input, request) {
      return await callBTT("callChatGPT", {
        identifier: "test",
        system: "you are a helpful assistant",
        user: request,
        input: input,
        maxHistory: 0,
      });
    }
    async function BTTInitialize() {
      let selectedText = await callBTT("get_string_variable", {
        variableName: "selected_text",
      });

      let res = await chatGPTRequest(selectedText, "make uppercase");
      document.getElementById("result").innerHTML = res;
      document.getElementById("loader").style.display = "none";
    }
  </script>
  <body>
    <div
      id="loader"
      style="
        with: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        align-content: center;
        justify-content: center;
      "
    >
      <div class="lds-dual-ring"></div>
    </div>
    <div id="result"></div>
  </body>
</html>

You just need to save the selected text before opening the webview:

1 Like

Thanks, but in the end I found a better solution: showing the clipboard after executing the transformation. I think this option provides a better graphical interface and also allows for further modification of the obtained text.

Would it be possible to add a "Transform & Copy selection With ChatGPT" action like the one for Javascript?

Hi @Andreas_Hegenberg, I set up 'Transform & Replace Selection With ChatGPT' yesterday with my own API key and it was working fine until earlier this morning when I set up a second trigger which asked for a prompt instead of working with a predefined one. However the second trigger I set up did not work and the first one has stopped working as well. I just get a blank entry in the clipboard whenever I run the trigger. I also do not see any result when I run the text execute command in the app. Not sure what's gone wrong here..

Is your token still working in general?
Here a curl command you can use to test (replace YOUR_TOKEN_HERE with your token):

curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_TOKEN_HERE" \
    -d '{"model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": "test"}]}' \
    https://api.openai.com/v1/chat/completions
1 Like

Looks like it wasn't! Thanks! The integration is super useful btw!

Hi @rdrxn, could I ask you to share how you set up this workflow that prompts for input instead of using the predefined prompt, please?

Just check this box:

3 Likes

How do you in the BetterTouchTool increase the magnification of a floating webview window?