A beginner tried making a SlackBot app with [ChatGPT + GAS]
Tags: slack, chatgpt, gas, beginners
Published: 2023-07-04 14:53:20

<h3>self-introduction</h3>
Nice to meet you, I'm K, an engineer at ocomoji.
I made a SlackBot app with GAS using the recently popular ChatGPT API, so I'll introduce it.

<h3>Introduction</h3>
I use Slack as a communication tool at work,
so Slack is always running, but to use chatGPT, I had to start the browser every
time . That's right, if you create a chatGPT BOT application with Slack, you can solve it !?
"
Since it was my first time, I developed it while researching from scratch
(80% thanks to articles by others ^^;)

<h3>what i wanted to do</h3>
Create a bot that returns an answer from chatGPT when you post on a channel that the created SlackBot is participating in

<h3>Advance preparation</h3>
Slack, GAS (GoogleAppsScript), and OpenAI (chatGPT) accounts must be prepared and ready to use (including permissions)

<h3>Development table of contents</h3>

1. [Create a URL for receiving post events from Slack with GAS](#title1)

1. [Create a SlackBot app](#title2)

1. [Get a token to use the SlackBot app](#title3)

1. [Add Slack library to GAS](#title4)

1. [Get a member ID to use the SlackBot app](#title5)

1. [Get an API key to use chatGPT](#title6)

1. [Link SlackBot app and chatGPT to GAS ~Settings~](#title7)

1. [Add the SlackBot app to your Slack channel](#title8)

1. [Connect SlackBot app and chatGPT to GAS](#title9)

1. [[Troubleshooting] Operation check - Communication - [GAS + SlackBot]](#title10)

1. [[Troubleshooting] Operation check - communication - [GAS + chatGPT]](#title11)

1. [[Troubleshooting] Secret trick](#title12)

<h3 id="title1">1. Create a URL for receiving post events from Slack in GAS</h3>
Enable GAS to receive posts from Slack

1.Start GAS ( https://script.google.com/home )

2.Press new project (project name and file name are optional)

3.Overwrite the existing code with the following code (overwrite with the save project button)

```Javascript
//Receive post from Slack
	function doPost(e) {
		//Parse received data (parse and extract data) 
		const postParam = JSON.parse(e.postData.getDataAsString());

		//Challenge authentication
		//①This authentication process is NG
		/*
		if (postParam.type === 'url_verification') {
			return ContentService.createTextOutput(postParam.challenge);
		}
		*/
		
		//②This authentication process is OK
		if('challenge' in postParam){
			return ContentService.createTextOutput(postParam .challenge); return}
```
　* The function name "doPost" is an event (reserved word ) so do not change it arbitrarily (I thought it was a non-reserved word)
It didn't work well When I
　looked into other articles, 2 authentication was also introduced, so when I implemented it, it worked well Has the
　GAS specification changed?

4.Deployment execution

(Deployment → New deployment → Select type: Web application → Accessible users: Everyone → Press deploy button)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e1acqjxba3tau06gyksu.png)

5.On the deployment completion screen, copy the URL of the web application and
press the memo completion button.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/32mcr8aw4tmslrgwcgfb.png)
We will check in step 2 to see if authentication from Slack to GAS has passed, so please try creating it in order 1 for the time being.

<h3 id="title2">2. Create a SlackBot app</h3>
The SlackBot app page is in English, so it's hard to see ^^;
1.Launch SlackAPI ( https://api.slack.com/apps )
2.Press Create New App Select
From scratch Select
App Name and Pick a workspace to develop your app in
*The name of the app I created this time is "chatGPT2" Press
Create App
3.Press Event Subscriptions on the sidebar Toggle Enable Events and paste the URL for receiving post events from Slack (URL created in order 1) in
On Request URL *Authentication succeeded when Verified is displayed! Add the following event with Subscribe to bot events → Add Bot User Event 　app_mention: Specify mention 　message.channels: Post message to channel Press Save Changes


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kgjmulfieb9mvq9qbahw.png)
4.Press OAuth & Permissions on the sidebar Add
the following scopes with Scopes → Bot Token Scopes → Add an OAuth Scope
　chat: write: message
　posting Press
for Your Workspace
　Install to Workspace Press
　Allow

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gcfa182ccnjdl2uua4wf.png)

<h3 id="title3">3. Get a token to use the SlackBot app</h3>
Get a token for your SlackBot app (something like an ID)
1.Launch SlackAPI ( https://api.slack.com/apps )
2.Press OAuth & Permissions in the sidebar
3.Copy OAuth Tokens for Your Workspace Bot User OAuth Token and make a note of it

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kxrgo2hhrzh5192zahgk.png)

<h3 id="title4">4. Add Slack library to GAS</h3>
Add SlackAPI library to GAS
1.Start GAS ( https://script.google.com/home )
2.Press + on Library
3.Add library
4.Copy and paste the following ID in the script ID and press search[1on93YOYfSmV92R5q59NpKmsyWIQD8qnoLYk-gkQBI92C58SPyA2x1-bqbr］
5.Press the add button (version and ID are OK with the initial values)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/athlsjmbj7pmserquavd.png)

<h3 id="title5">5. Add SlackBot app to Slack and get member ID</h3>
Add the created bot app to Slack and get the member ID
1.Launch Slack
2.Sidebar → Add application → Search by chatGPT2 → Press the corresponding application
3.Since chatGPT2 is added to the sidebar, press chatGPT2 to launch the profile

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3r2i5hn5ehlg4vs8obv2.png)
4.Copy the member ID and make a note of it

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wwx6fihwmg9n9151yhik.png)

<h3 id="title6">6. Get an API key to use chatGPT</h3>
1.Launch OpenAI ( https://platform.openai.com/overview )
2.login
3.Click on your account icon on the top right
4.Press View API keys
5.Press Create new secret key
6.The displayed key is your API key. copy and note

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/12ksxy9b2trge25d1tq5.png)

<h3 id="title7">7. Connect SlackBot app and chatGPT to GAS ~Settings~</h3>
Configure SlackBot app and chatGPT linkage settings to GAS
1.Start GAS ( https://script.google.com/home )
2.Press the gear mark (settings) on the sidebar
3.Press Add script property and add three as shown in the image below
　openApiKey: OpenAI's API key for using chatGPT. Get from OpenAI account (order 6)
　slackBotId: SlackBot app member ID. Get from Slack app (order 5)
　slackBotToken: SlackBot app token. Get from browser. Bot User OAuth Token (order 3)
4.Press save script properties

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3r86xlb2lyn74kvnhc4s.png)

<h3 id="title8">8. Add the SlackBot app to your Slack channel</h3>
1.Launch Slack
2.Press any channel to launch the property screen
3.Press integration on the top tab
4.press add app
5.The created SlackBot (chatGPT2) will appear in the list, so press Add

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ji0jrl7ubhiy66dftjkb.png)

<h3 id="title9">9. Connect SlackBot app and chatGPT to GAS ~Code~</h3>
Implemented SlackBot and chatGPT linkage to GAS
1.Start GAS ( https://script.google.com/home )
2.Overwrite the existing code in GAS with the following code (overwrite with the save project button)

```Javascript
	//Receive posts from Slack
	//**********  START Main **********
	function doPost(e) {
	  //Parse received data Extraction
	  const postParam = JSON.parse(e.postData.getDataAsString());
	  
	  //Challenge authentication

	  //1.This authentication process is NG
	  /*
	  if (postParam.type === 'url_verification') {
	    return ContentService.createTextOutput(postParam.challenge);
	  }
	  */

	  //2. OK with this authentication process
	  if('challenge' in postParam){
	    return ContentService.createTextOutput(postParam.challenge);
	  }
	  
	  //3.Return the sentence to the channel posted on Slack
	  //sendSlack(postParam.event.channel, 'Catch the post from Slack! GAS will reply!');

	  //Event retransmission avoidance
	  //Processed if loaded in cache
	  //Stacked in cache if unprocessed (validity period 5m)
	  const event_id = postParam.event_id;
	  const cache = CacheService.getScriptCache();
	  const isProcessed = cache.get(event_id);

	  if (isProcessed)　return;

	  cache.put(event_id, true, 601);

	  //event with subtype set 
	  if('subtype' in postParam.event) return;

	  //When sent by ChatGPTBot
	  //Create a response message in ChatGPT and send it to Slack
	  const botId = PropertiesService.getScriptProperties().getProperty('slackBotId');
	  if (postParam.event && postParam.event.user !== botId) {
	    const channel = postParam.event.channel;
	    const text = postParam.event.text;
	    var message = requestChatGPT(text);

	    sendSlack(channel, message);
	  }

	  return;
	}
	//**********  END MAIN **********


	//4.　**********  START [Troubleshooting] Operation check - communication - [GAS + chatGPT] **********
	function testGAStoChatGPT() {
	  console.log(requestChatGPT(" What is chatGPT?"));
	}
	//**********  END [Troubleshooting] Operation check - communication - [GAS + chatGPT] **********


	//**********  START Send message through SlackBots **********
	//20230301 Confirmed that this works by itself
	function sendSlack(channel, message) {
	  const slackToken = PropertiesService.getScriptProperties().getProperty('slackBotToken');
	  const slackApp = SlackApp.create(slackToken);
	  slackApp.postMessage(channel, message);
	}
	//**********  END Send message through SlackBots**********


	//**********  START Send text to ChatGPT and get response message **********
	//20230301 20230301 Confirmed that this works by itself
	function requestChatGPT(message) {

	  const apiKey = PropertiesService.getScriptProperties().getProperty('openApiKey');
	  const apiUrl = 'https://api.openai.com/v1/chat/completions';
	  
	  //Request Data Settings
	  const headers = {
	    'Authorization':'Bearer '+ apiKey,
	    'Content-type': 'application/json'
	  };
	  const options = {
	    'headers': headers, 
	    'method': 'POST',
	    'payload': JSON.stringify({
	      //Specify model gpt-3.5-turbo:chatGPT text-davinci-003:GPT-3
	      'model': 'gpt-3.5-turbo',
	      //Specify the maximum number of tokens in the generated text. like word count
	      'max_tokens' : 1500,
	      //If you specify 0.5, the generated sentences tend to be similar to the input sentence
	      //If you specify 1.0, the generated sentences will be more diverse
	      'temperature': 0.5,
	      //Specify a query string
	      'messages': [{ role: "user", content: message }]
	    })
	  };

	  //Send a request and get the result
	  const response = JSON.parse(UrlFetchApp.fetch(apiUrl, options).getContentText());
	  const resMessage = response.choices[0].message.content;

	  return resMessage;
	}
	//********** END Send text to ChatGPT and get response message **********

```
3.Redeploy with the following procedure
 1.Deployments → Manage Deployments → Pencil Mark (Edit)
 2.Press the version and select [New version] *1
 3.press deploy
 4.Press Approve access
 5.After that, permission confirmation for access appears several times, but all are permitted

*If there is an error in the redeployment procedure,
　the URL will be different from the web application URL when SlackBots was created, and it will not work

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9pwg5nk3019rc8415bhf.png)
 4.Mention your bot and ask questions in any channel where you 
 added the SlackBot app
 5.Answers are returned from the SlackBot app
 6.Cooperation success! good job for today!


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bck3o4mmv7s0x8i9pum5.png)

<h3 id="title10">10. [Troubleshooting] Communication check [GAS → SlackBot]</h3>
If there is no reply from SlackBot, perform a communication test to see if GAS and SlackBot are linked Communication
flow: Slack → GAS → chatGPT →　**GAS → Slack**
 1,Start GAS ( https://script.google.com/home )
 2.Uncomment 3 in the existing code (order 9) (delete the slash)
//sendSlack～～ → sendSlack～～
 3.Redeploy (order 9-3)
 4.@mention the bot in any channel where you added the SlackBot app and send an appropriate message
 5.From the SlackBot app, "Catch posts from Slack OK! I will reply from GAS! If you receive a reply that says, the 
communication is successful.
 6.Communication test success: Check the communication of GAS → chatGPT → GAS in the following order
Communication test failure: Review the settings between GAS and Slack
(For now, ignore chatGPT and implement simple processing with GAS + Slack and test good)
 7.Return the comment at 3 in the existing code (order 9) (restore the slash slash)
sendSlack～～ → //sendSlack～～
 8.Redeploy and return to the original state (order 9-3)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/atzlblmy434qkrvwx3gy.png)

<h3 id="title11">11. [Troubleshooting] Communication check [GAS → chatGPT → GAS]</h3>
If there is a reply from GAS to SlackBot but no reply from chatGPT (order 10 is a successful state), perform a communication test to see if GAS and chatGPT are linked Communication flow: Slack → GAS → chatGPT
→　**GAS**　→ Slack

 1.Start GAS ( https://script.google.com/home )
 2.Select function: testGAStoChatGPT from the right side of debug in the top menu
* Execute the function prepared in the existing code (order 9)
 3.Press the execution of the upper menu
 4.Successful communication when an answer from chtatGPT arrives in the execution log at the bottom

 5.Successful communication test:
　Check Slack → GAS communication. You can ignore it and implement a simple process with GAS + chatGPT and test it.)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3a2fzuvtexs5lq7u84qx.png)

<h3 id="title12">12. [Troubleshooting] Tricks</h3>
If it doesn't work so far, please delete the created GAS/SlackBot app and try to create it from 1. But it doesn't work when it comes to the integration test><' I didn't know the cause, so I thought it would be better to hurry, so I recreated it from order 1 and it worked normally.

<h3>struggled</h3>

1.Challenge authentication (order 1)

2.It worked at the component level, but it didn't work when combined (correspond in order 　12
)
There seems to be a way, so if I could do that, I might have been able to develop efficiently.
　
3.**Struggling with JavaScript in GAS**
There is "function doPost (e) {" in the code (order 9), but I recognized it as "a function that receives posts from Slack named doPost" I found out later (because I referred to other people's articles for this part),
but doPost was "a GAS-only event that receives posts from Slack, not a function" *To be exact, it is an event
that accepts HTTP POST .

without realizing it, where are the post events from Slack? I was confused and had a hard time understanding the code. Cry
doPost The function name is difficult to understand, so let's change it! By taking action, the parts that had been working until now stopped working, and it was even more confusing... If you search for "GAS doPost", the explanation article will be staggered, and it will be easily resolved
. later in my impressions

4.Slack, GAS, and chatGPT_API are used, and the procedure is long and I feel like I'm going to break my heart!
**Patience** is required

<h3>Impressions after trying to make it</h3>
In order to realize this project, it was necessary to understand three tools: GAS, Slack application, and chatGPT_AI
. When I tried to create it, I had a hard time, but I was able to realize it surprisingly easily (thanks to the article of others )

. It must be a function because it has a function, but there is no event that executes
this function anywhere!" I thought so based on my experience and intuition
.・ There are many cases where [relying on one's own experience and intuition] leads to shortcuts, but it's not everything, and sometimes it's also important to [question one's own experience and intuition].It was a good experience for the first time . It's something I use, so I think I could have developed it without having to struggle in strange places if I researched more in advance about what GAS is, what is a Slack app, etc. Create a bot that returns an answer from]

This is what I wanted to do.
Future tasks will be described below, but I hope that I can update it from time to time because it is a bot that can still grow.

<h3>Future tasks</h3>
1.Learn the log output function of GAS
2.Use jQuery library with GAS
3.Reply to thread from bot
4.Reply speed from bot UP
5.Character settings (ocomoji-kun!)

<h3>bonus</h3>
After changing and redeploying part of the existing code 2.(order 9) that I had chatGPT itself check for [lie], which is a weak point of chatGPT, I

threw a question to the bot as follows.

```Javascript
//If ChatGPTBot sent //Create a response message in ChatGPT and send it to Slack const botId = PropertiesService.getScriptProperties ( ) . getProperty ( ' slackBotId ' ) ; if ( postParam.event && postParam.event.user ! = = botId ) { const channel = postParam.event.channel ; const text = postParam.event.text ; _ _ _ _ _ _ _ _

	   	    
	    var message = requestChatGPT ( text ); // Let yourself do a fact check 
	    sendSlack ( channel , "[Before fact check]\n" + message );  
	    message = "Fact check the following and then reply again \n\n" + message ; 
	    message = requestChatGPT ( message ); 
	    sendSlack ( channel , "[after fact check]\n" + message ) ;
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8un2wh1m9f49jt0lyh7m.png)


Kashima City doesn't have Kashima Higashi High School or Kashima South High School.
What kind of answer will you get if you do multiple fact checks?
                        	

<h4>We are ocomoji Corporation, an RPA and business efficiency company in Saga, Japan.
Please feel free to contact us.
</h4>
[ocomoji.co "Bring DX closer to you."](https://ocomoji.co.jp/)