{"componentChunkName":"component---src-pages-markdown-remark-fields-slug-js","path":"/engineering/creating-a-google-hangout-bot-with-express-and-node-js/","result":{"data":{"markdownRemark":{"id":"ced9f3b5-ac7d-5aea-a05f-96f4f5eeff80","excerpt":"Time Required: 20 minutes. Technologies: Express, Node.js, JavaScript. Prerequisites: Basic knowledge of Express, Node.js, and JavaScript. Node.js and npm are…","html":"<p>Time Required: 20 minutes.<br>\nTechnologies: Express, Node.js, JavaScript.<br>\nPrerequisites:</p>\n<ul>\n<li>Basic knowledge of Express, Node.js, and JavaScript.</li>\n<li>Node.js and npm are installed.</li>\n</ul>\n<p>This tutorial will go over how to build a bot that will respond to pings (i.e. @<bot-name>), and send messages to a chat room. On a high level, the bot will run on an express server, and receive pings via an HTTP endpoint. Responses to pings will be sent synchronously through a payload in the HTTP response, while bot-initiated messages will be sent asynchronously using the Google Hangout Chat API.</p>\n<h5 id=\"outline\" style=\"position:relative;\"><a href=\"#outline\" aria-label=\"outline permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Outline</strong></h5>\n<ol>\n<li>Environment setup.</li>\n<li>Get bot to respond to pings.</li>\n<li>Send bot-initiated messages.</li>\n<li>Deploy.</li>\n</ol>\n<h5 id=\"environment-setup\" style=\"position:relative;\"><a href=\"#environment-setup\" aria-label=\"environment setup permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Environment Setup</strong></h5>\n<p>Create a new project with the file ‘app.js’.<br>\nOpen command line/terminal, and navigate to your project directory. Run ‘npm init’, and press enter until package.json is created. Next, install the following dependencies:</p>\n<ul>\n<li>express: <code>npm install express --save</code></li>\n<li>body-parser:  <code>npm install body-parser --save</code></li>\n<li>googleapis: <code>npm install googleapis --save</code></li>\n<li>unirest:  <code>npm install unirest --save</code></li>\n</ul>\n<p>In ‘app.js’, let’s setup our server:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">express</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;express&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">bodyParser</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;body-parser&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">google</span><span class=\"mtk1\"> } = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;googleapis&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">express</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">(</span><span class=\"mtk12\">bodyParser</span><span class=\"mtk1\">.</span><span class=\"mtk11\">urlencoded</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">extended:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">false</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}));</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">(</span><span class=\"mtk12\">bodyParser</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">());</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">listen</span><span class=\"mtk1\">(</span><span class=\"mtk7\">8100</span><span class=\"mtk1\">, </span><span class=\"mtk4\">function</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;App listening on port 8100.&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<p>Running ‘node app.js’ will now create a local server on port 8100.</p>\n<h5 id=\"responding-to-pings\" style=\"position:relative;\"><a href=\"#responding-to-pings\" aria-label=\"responding to pings permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Responding to Pings</strong></h5>\n<p>The bot will respond to pings through a HTTP POST endpoint. Create one with express:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;/&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;someone pinged @&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\">.</span><span class=\"mtk12\">type</span><span class=\"mtk1\"> === </span><span class=\"mtk8\">&#39;MESSAGE&#39;</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">text:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;sleeping...&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<p>The bot will respond with the text: ‘sleeping…’.</p>\n<p>Synchronously responding to messages simply requires us to return a response to Google. The downside to this is the 30 second time limit before Google no longer accepts responses to the request. For instance, this would be a problem if you were building some kind of reminder app; the bot wouldn't be able to synchronously respond after 30 seconds. This is where async responses come in.</p>\n<h5 id=\"bot-initiated-messages\" style=\"position:relative;\"><a href=\"#bot-initiated-messages\" aria-label=\"bot initiated messages permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Bot-initiated Messages</strong></h5>\n<p>To show this, we will have our bot post to a chat room every 1 minute.</p>\n<p>Sending async messages to Google API requires a Service Account for authentication. Once authenticated, we can make a POST request to a Google API URL that will create a message.</p>\n<p>So first, create a Google Service Account following these <a href=\"https://developers.google.com/hangouts/chat/how-tos/service-accounts\">steps</a>. Take the downloaded JSON file and put it in the root directory of your project. Here, we renamed it to googlekeys.json:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">gkeys</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;./googlekeys.json&#39;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>We will be making POST requests using Unirest:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">unirest</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;unirest&#39;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Now generate a JWT that will be used in our POST request:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">getJWT</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Promise</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">resolve</span><span class=\"mtk1\">, </span><span class=\"mtk12\">reject</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">jwtClient</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">google</span><span class=\"mtk1\">.</span><span class=\"mtk10\">auth</span><span class=\"mtk1\">.</span><span class=\"mtk10\">JWT</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">gkeys</span><span class=\"mtk1\">.</span><span class=\"mtk12\">client_email</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">null</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">gkeys</span><span class=\"mtk1\">.</span><span class=\"mtk12\">private_key</span><span class=\"mtk1\">, [</span><span class=\"mtk8\">&#39;https://www.googleapis.com/auth/chat.bot&#39;</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    );</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">jwtClient</span><span class=\"mtk1\">.</span><span class=\"mtk11\">authorize</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\">, </span><span class=\"mtk12\">tokens</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">err</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;Error create JWT hangoutchat&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">reject</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      } </span><span class=\"mtk15\">else</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">resolve</span><span class=\"mtk1\">(</span><span class=\"mtk12\">tokens</span><span class=\"mtk1\">.</span><span class=\"mtk12\">access_token</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Here is our function for posting messages. ROOM-ID can be found in the URL of the hangout chat room page i.e.: <code>https://chat.google.com/u/0/room/{ROOM-ID}</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">postMessage</span><span class=\"mtk1\">(</span><span class=\"mtk12\">count</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Promise</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">resolve</span><span class=\"mtk1\">, </span><span class=\"mtk12\">reject</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk11\">getJWT</span><span class=\"mtk1\">().</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">token</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk12\">unirest</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;https://chat.googleapis.com/v1/spaces/&#39;</span><span class=\"mtk1\"> + {ROOM-</span><span class=\"mtk12\">ID</span><span class=\"mtk1\">} + </span><span class=\"mtk8\">&#39;/messages&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              .</span><span class=\"mtk11\">headers</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                  </span><span class=\"mtk8\">&quot;Content-Type&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;application/json&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                  </span><span class=\"mtk8\">&quot;Authorization&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Bearer &quot;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">token</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              .</span><span class=\"mtk11\">send</span><span class=\"mtk1\">(</span><span class=\"mtk10\">JSON</span><span class=\"mtk1\">.</span><span class=\"mtk11\">stringify</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                  </span><span class=\"mtk8\">&#39;text&#39;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;Hello! This is message number &#39;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">count</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              }))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              .</span><span class=\"mtk11\">end</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">res</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                  </span><span class=\"mtk11\">resolve</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }).</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk11\">reject</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Finally, add the code that will repeat our post every minute.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">timer</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;timers&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">listen</span><span class=\"mtk1\">(</span><span class=\"mtk7\">8100</span><span class=\"mtk1\">, </span><span class=\"mtk4\">function</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;App listening on port 8100.&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">count</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">timer</span><span class=\"mtk1\">.</span><span class=\"mtk11\">setInterval</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk11\">postMessage</span><span class=\"mtk1\">(</span><span class=\"mtk12\">count</span><span class=\"mtk1\"> += </span><span class=\"mtk7\">1</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }, </span><span class=\"mtk7\">60000</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<h5 id=\"deploy\" style=\"position:relative;\"><a href=\"#deploy\" aria-label=\"deploy permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Deploy</strong></h5>\n<p>Expose your local server to public (we used <a href=\"https://ngrok.com/\">ngrok</a>).</p>\n<p>Login to <a href=\"https://console.developers.google.com\">developer console</a>. Create a new project, and enable Hangout Chat API. Under configuration, set:</p>\n<ul>\n<li>status: live</li>\n<li>bot name (this is how you will add and ping the bot)</li>\n<li>avatar</li>\n<li>description</li>\n<li>functionality: rooms</li>\n<li>connection settings - bot URL: <your ngrok HTTPS url></li>\n<li>permission: everyone in your domain</li>\n</ul>\n<p>Restart your local server, and that’s it! Make sure you have your bot added to the chat room, and you can ping it by sending @<bot-name>. The bot will also post to the chat room every minute.</p>\n<p>There are a lot of different ways to further extend this bot, such as setting reminders/notifications, making to-do lists, displaying server logs, and interacting with API’s.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 456px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 98.90350877192984%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAABiElEQVQ4y41TybKCMBDk/7/M7faKix60WAKIEBKW7Pga8/QdlDJdldSkoGcmneloGAattZRSCPEMpPTnb4jwm1IKtHmePd85Z7Hu3xFh7ff77XZrrT2dToSQprmlOakon6aJc450q2R8Y4wVZQky6zpGadu212tVkLyu6zzPca9VMlr1kXFOODtaI99anlfwTxbGZD2Pm2s+8HsYIkpp9wBnrGd84Bw7jiwAi9poYFHYWr8/A+Nh17GofT6fsyxDiqIoUBPpWD9OLuyp4jg+HA6Q/Xy55IQUhCRAtqidpinSec0+kNHYn57YnZvRs7UYGyEmP3D+h8+VX9+kNeU4HGlTjn2o2n4wAWVMK8Z67JkUXkKPeR0RZhD8ZbyVgsBo22qjHnj4Q76Cd0T+PZYK91kbDYv4WvdAY2w2m91uhxTH47GqKkwLKatbvzjM+2yVjJodpTAA+l080TR4IXgrTRMkCnoqAN2qhzfM7ELVfpEnoxPOfuoy4V0o2d8KOhmtobbDMBuEQfgFyzeOgOEE8E8AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"image2\"\n        title=\"image2\"\n        src=\"/static/01e633c666a77beb405600b9e10f32a8/7f664/image2.png\"\n        srcset=\"/static/01e633c666a77beb405600b9e10f32a8/7f664/image2.png 456w\"\n        sizes=\"(max-width: 456px) 100vw, 456px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 300px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 41.333333333333336%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAwElEQVQY042POQ7CMBBFfX6OQAEn4Aq0IBaJggYIFFaUhGyO4yz2jD0mRNQkrxzp//mP9X3vvSdH1lpnf6CdBQMDy/NiF25FXgevJ+dcCFG22vlpmDGwua0vye7dmSCNizwf7+TnhBEh4gloVHWtlALdhVW3uumotd+OvyVsmL4/7JMkTrPsfn9UomzAHVNQQJMDmNbaEqJDtGiMQcQxQkRuAnKDs7mmp7jhUsimbfx84+GzlDIqwrzKBuV61J7PB66zz8uuwzWBAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"image1\"\n        title=\"image1\"\n        src=\"/static/0f2b5c8c3421fb1370ecf03c036718fe/5a46d/image1.png\"\n        srcset=\"/static/0f2b5c8c3421fb1370ecf03c036718fe/5a46d/image1.png 300w\"\n        sizes=\"(max-width: 300px) 100vw, 300px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n</style>","headings":[{"value":"Outline","depth":5},{"value":"Environment Setup","depth":5},{"value":"Responding to Pings","depth":5},{"value":"Bot-initiated Messages","depth":5},{"value":"Deploy","depth":5}],"fields":{"slug":"/engineering/creating-a-google-hangout-bot-with-express-and-node-js/"},"frontmatter":{"metatitle":null,"metadescription":null,"description":null,"title":"Creating a Google Hangout Bot with Express and Node.js","canonical":null,"date":"June 06, 2018","updated_date":null,"tags":["Express","NodeJs","Hangout"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/f62c49828f8a2a1d1483abd689ceb93e/7e9eb/hangoutchatimgage2.jpg","srcSet":"/static/f62c49828f8a2a1d1483abd689ceb93e/3dcee/hangoutchatimgage2.jpg 200w,\n/static/f62c49828f8a2a1d1483abd689ceb93e/ae6ae/hangoutchatimgage2.jpg 400w,\n/static/f62c49828f8a2a1d1483abd689ceb93e/7e9eb/hangoutchatimgage2.jpg 630w","sizes":"(max-width: 630px) 100vw, 630px"}}},"author":{"id":"Andy Yeung","github":null,"bio":"Software Developer at LoginRadius with an interest in big data and basketball..","avatar":null}}}},"pageContext":{"id":"ced9f3b5-ac7d-5aea-a05f-96f4f5eeff80","fields__slug":"/engineering/creating-a-google-hangout-bot-with-express-and-node-js/","__params":{"fields__slug":"engineering"}}},"staticQueryHashes":["1171199041","1384082988","1711371485","1753898100","2100481360","229320306","23180105","528864852"]}