<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Isak Solheim</title>
    <description>The latest articles on DEV Community by Isak Solheim (@isaksolheim).</description>
    <link>https://dev.to/isaksolheim</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F829204%2F331b3f7c-56d2-4448-803a-0106837b55ff.jpeg</url>
      <title>DEV Community: Isak Solheim</title>
      <link>https://dev.to/isaksolheim</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/isaksolheim"/>
    <language>en</language>
    <item>
      <title>Moving to Berlin using ChatGPT and JavaScript</title>
      <dc:creator>Isak Solheim</dc:creator>
      <pubDate>Mon, 11 Dec 2023 09:24:46 +0000</pubDate>
      <link>https://dev.to/isaksolheim/moving-to-berlin-using-chatgpt-and-javascript-3b0k</link>
      <guid>https://dev.to/isaksolheim/moving-to-berlin-using-chatgpt-and-javascript-3b0k</guid>
      <description>&lt;p&gt;&lt;strong&gt;TLDR&lt;/strong&gt;: I built a bot that automatically sends personalized, context-aware messages to every new listing posted on &lt;a href="https://www.wg-gesucht.de/"&gt;wg-gesucht.de&lt;/a&gt;. The bot found me a flat in Berlin!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you’re interested in the technical side of this project, feel free to &lt;a href="https://github.com/isaksolheim/gesucht"&gt;dig through the code&lt;/a&gt; while reading this article!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;As my exchange semester at Technische Universität Berlin approached, I started looking for places to live. Without an existing network in Berlin, I used the website &lt;a href="https://www.wg-gesucht.de/"&gt;wg-geuscht.de&lt;/a&gt; to contact potential flatshares. This was a very repetitive process, and I decided to automate it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automate the Boring Stuff with JavaScript
&lt;/h2&gt;

&lt;p&gt;I set up email alerts for all new potential flats in my price range on &lt;a href="https://www.wg-gesucht.de/"&gt;wg-gesucht.de&lt;/a&gt;, and used Google Clouds &lt;a href="https://cloud.google.com/pubsub/docs/overview"&gt;Pub/Sub service&lt;/a&gt; with a &lt;a href="https://cloud.google.com/pubsub/docs/push"&gt;push subscription&lt;/a&gt; to watch for any incoming email to my Gmail inbox.&lt;/p&gt;

&lt;p&gt;Once a new email arrives, the service sends a webhook notification to my server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parsing the email
&lt;/h3&gt;

&lt;p&gt;On the server, written in JavaScript with &lt;a href="https://github.com/expressjs/express"&gt;Express&lt;/a&gt;, I read the latest email in my Gmail inbox and parse it with Regex to see if the email contains links to any wg-geuscht listings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navigating the listing
&lt;/h3&gt;

&lt;p&gt;For each listing, I spawn a chromium browser using &lt;a href="https://playwright.dev/"&gt;Playwright&lt;/a&gt;, an end-to-end testing framework. This allows me to navigate the website just as one would when interacting with it themselves. I sign into my account, take note of the listing description, and hit send message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generating a message using GPT-3.5 Turbo
&lt;/h3&gt;

&lt;p&gt;The message is generated using &lt;a href="https://platform.openai.com/docs/models/gpt-3-5"&gt;GPT-3.5 Turbo&lt;/a&gt; with the following prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
Can you spice up the following text: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;starterText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"
The updated text should explain why I would fit in the
flatshare with the following listing text: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;listingText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;".
Add some emojies as well. Mention that my semester is from
September to March, so a stay for that perioud would be ideal
(but Im always flexible)! And if the listing is written in
German, the answer should be in German as well. And if the 
listing says I need to say a specific word, start the whole 
text with that word!
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated message was sent alongside a couple of images of myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;The time it took from a listing went live to my bot had sent a response was around 10 seconds, making me confident in being the first responder. This was the response that secured me a flat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hallo zusammen! 🦄

Das scheint ja eine richtig coole WG zu sein, in die ich perfekt reinpassen würde! 😄

Ich bin Isak und ich glaube, dass ich perfekt in dein WG-Zimmer passen würde! Mein Semester in Berlin geht von September bis März, also wäre ein Aufenthalt für diesen Zeitraum ideal (aber ich bin auch immer flexibel!). Die Lage der Wohnung klingt super, besonders die Nähe zum RAW-Gelände und zum Boxhagener Platz. Und hey, eine Tram-Station direkt vor der Tür ist auch genial! 🚋

Die Wohnung hört sich toll an, mit Balkon, Badewanne und Waschmaschine. Da fühlt man sich doch gleich wie zuhause! Wenn du Interesse hast, würde ich mich freuen, von dir zu hören. 📞

Liebe Grüße und hoffentlich bis bald!

Isak

P.S. Wenn die Anzeige auf Deutsch ist, dann antworte ich auch gerne auf Deutsch. Aber sei gewarnt, mein Deutsch ist manchmal etwas holprig. Ich verstehe nur Bahnhof! 😄
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;Looking back, I spent more time tinkering with the bot than I would have manually responding to email notifications. But with that being said, I am happy with how this project turned out. I got a lot of laughs from the silly responses the bot would send, and the frequency of people getting back to me was noticeably increased (most likely because I was their first responder).&lt;/p&gt;

&lt;p&gt;I recently tried spinning the bot up again, but since my search in June, captcha verification has been implemented on their site. This may be for the better. For all I know many of the listings themselves were created using ChatGPT.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>chatgpt</category>
      <category>automation</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Creating a Slackbot With JavaScript Bolt</title>
      <dc:creator>Isak Solheim</dc:creator>
      <pubDate>Fri, 08 Dec 2023 14:58:06 +0000</pubDate>
      <link>https://dev.to/isaksolheim/creating-a-slackbot-with-javascript-bolt-1kp7</link>
      <guid>https://dev.to/isaksolheim/creating-a-slackbot-with-javascript-bolt-1kp7</guid>
      <description>&lt;p&gt;Creating a SlackBot that reacts to every message sent by a specific user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R3CULgGC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://photos.isaks.cloud/2022-12-10-bot-reaction_1280.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R3CULgGC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://photos.isaks.cloud/2022-12-10-bot-reaction_1280.webp" alt="Bot reacting with heavy_plus_sign" width="800" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a New Slack App
&lt;/h2&gt;

&lt;p&gt;The first thing we have to do is create a new slack app. We do this by navigating to &lt;a href="https://api.slack.com/"&gt;api.slack.com&lt;/a&gt; and navigating to &lt;code&gt;Your Apps -&amp;gt; Create New App&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We’ll call our app &lt;code&gt;reacting-bot&lt;/code&gt;. Next up, we have to set up &lt;em&gt;event subscriptions&lt;/em&gt;, a &lt;em&gt;bot user&lt;/em&gt;, and &lt;em&gt;permissions&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Socket Mode
&lt;/h3&gt;

&lt;p&gt;The first thing we have to do is enable Socket Mode. Turning on Socket Mode will route your app’s interactions and events over a WebSockets connection instead of sending these payloads to different Request URLs.&lt;/p&gt;

&lt;p&gt;To enable Socket Mode, navigate to &lt;code&gt;Settings -&amp;gt; Socket Mode&lt;/code&gt; and hit &lt;em&gt;Enable Socket Mode&lt;/em&gt;. You will be prompted to add scopes and generate an app-level token. Give the token a name, e.g., “token”, and add the following scopes:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;connections:write&lt;/code&gt; &amp;amp; &lt;code&gt;authorizations:read&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As the names suggest, these will give our app permission to read and write messages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Event Subscriptions
&lt;/h3&gt;

&lt;p&gt;Next up, we need to enable Event Subscriptions, which can be found beneath &lt;code&gt;Features&lt;/code&gt; in the left-side menu. After enabling Event Subscriptions, you will need to add the following Event Subscriptions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subscribe to bot events:&lt;/strong&gt; &lt;code&gt;message.groups&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscribe to event on behalf of users:&lt;/strong&gt; &lt;code&gt;message.channels&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bot User
&lt;/h3&gt;

&lt;p&gt;If a Bot User has not yet been created, it can be set up on the &lt;code&gt;App Home&lt;/code&gt; tab. Here we can set a display name and its username.&lt;/p&gt;

&lt;h3&gt;
  
  
  Permissions
&lt;/h3&gt;

&lt;p&gt;Lastly, we need to ensure that the SlackBot has all the correct permissions needed. Head over to &lt;code&gt;OAuth &amp;amp; Permissions&lt;/code&gt; and add the &lt;code&gt;reactions.write&lt;/code&gt; permission to the &lt;strong&gt;Bot Token Scopes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We have now set up the SlackBot, and we are ready to start coding!&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing The Bot
&lt;/h2&gt;

&lt;p&gt;We will be using the &lt;code&gt;bolt-js&lt;/code&gt; library as an interface to the Slack API. It comes with many useful features that make creating SlackBots a breeze.&lt;/p&gt;

&lt;p&gt;While in a new directory &lt;code&gt;reacting-bot&lt;/code&gt;, we can initialize the project using &lt;code&gt;npm init -y&lt;/code&gt;. This will create a &lt;code&gt;package.json&lt;/code&gt; file that looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reacting-bot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISC"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this project, we are going to need two packages. &lt;em&gt;@slack/bolt&lt;/em&gt; and &lt;em&gt;dotenv&lt;/em&gt;. &lt;em&gt;Bolt&lt;/em&gt; is an interface that we use to communicate with the Slack API, and &lt;em&gt;dotenv&lt;/em&gt; is used to access environment variables. We can install the packages with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @slack/bolt dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next up, we need to create the file &lt;code&gt;.env&lt;/code&gt; which should store our environment variables for when we are running this project locally. The file should contain the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;SIGNING_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5c24e...
&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xoxb-...
&lt;span class="nv"&gt;APP_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xapp-...
&lt;span class="nv"&gt;USER_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;UCF8...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SIGNING_SECRET&lt;/code&gt; can be found on the &lt;strong&gt;Basic Information&lt;/strong&gt; page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TOKEN&lt;/code&gt; (xoxb) can be found on the &lt;strong&gt;OAuth &amp;amp; Permissions&lt;/strong&gt; page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;APP_TOKEN&lt;/code&gt; (xapp) can be found on the &lt;strong&gt;Basic Information&lt;/strong&gt; page under &lt;strong&gt;App-level tokens&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;USER_ID&lt;/code&gt; can be found when viewing a slack profile under &lt;strong&gt;More&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;In &lt;code&gt;index.js&lt;/code&gt;, we start by importing &lt;code&gt;@slack/bolt&lt;/code&gt; and &lt;code&gt;dotenv&lt;/code&gt;, and we initialize a bolt application in socket mode in the constant &lt;code&gt;app&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@slack/bolt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;signingSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SIGNING_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;socketMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;appToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APP_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then write the logic that uses the &lt;code&gt;message()&lt;/code&gt; method to attach a listener for messages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;USER_ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reactions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;botToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;heavy_plus_sign&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We check any given message is sent by the user with the &lt;code&gt;ID&lt;/code&gt; &lt;code&gt;USER_ID&lt;/code&gt;. If we find a match, we use the &lt;code&gt;app.client.reactions.add()&lt;/code&gt; function to add a reaction to the message.&lt;/p&gt;

&lt;p&gt;Lastly, we add a function that runs when the application starts. This function will start up the Slack App:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`⚡️ reacting-bot is running on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that’s it! You can now run the app using the &lt;code&gt;npm start&lt;/code&gt; command, and the bot will start reacting to messages once it has been added to the correct channels.&lt;/p&gt;

&lt;p&gt;This is what the final code looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@slack/bolt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;signingSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SIGNING_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;socketMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;appToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APP_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;USER_ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reactions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;botToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;heavy_plus_sign&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`⚡️ reacting-app is running on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks for checking out this guide! You can view the code for this project on my &lt;a href="https://github.com/isaksolheim/reacting-slackbot"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>slackbot</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
