The Discord Bot Using AI powered Serverless Skills

Blumareks
7 min readNov 20, 2020

In this blog post you will deploy a Discord Bot that would launch serverless action creating Bot-Backend-as-a-Service (BBaaS).

In order to start it you need to follow the following steps:

  1. Setup your Discord for using a Bot
  2. Create a standalone Bot or a containerized Bot
  3. (optional) Add AI based backend to your Bot
  4. (optional) Run your bot in a Cloud
  5. (optional) Add the Discord voice channel to your Bot
  6. (optional) Add Text-to-Speech to your voice Bot
  7. Add a skill to run Bot-Backend-as-a-Service

If you are interested in the Serverless Skills for your Bot (and to create your BBaaS) — go straight to Step 7.

So let’s start!

Step 1. Setup your Discord for using a Bot

Read about it here: https://medium.com/voice-tech-podcast/yeah-a-discord-ai-powered-bot-baby-d9cb73b4775d?source=friends_link&sk=5fd7e544211b3f64b8e5ca476dd547c9

Step 2. Create a standalone Bot or a containerized Bot

In the above link search for the Paragraph 2: The Discord Node JavaScript library and Paragraph 2a: Instead of doing native Node.js go with Containers

These two paragraphs describe in the detail on how to use the Discord.js library in the standalone Discord bot program, or in the containerized one with Docker.

Step 3. (optional) Add AI based backend to your Bot

Read about it here: https://medium.com/zero-equals-false/add-ai-to-discord-bot-with-watson-fdcca207869d?source=friends_link&sk=6e0c5f7e711b8f6fb9c3959c4cddaa24

Step 4. (optional) Run your bot in a Cloud

Running a bot in the cloud makes it always on — your PC might get turned off, and then your bot will cease to exist. With the cloud you would run it in Kubernetes cluster with always on infrastructure — check it here on how to test it and spin a cluster for your Discord bot for free: https://blumareks.medium.com/always-on-discord-bot-in-the-cloud-%EF%B8%8F-with-the-ai-powered-chatbot-4c18503a1c49

Step 5. (optional) Add the Discord voice channel to your Bot

Eventually you might want your Discord bot to respond to the cues of your users and play sounds. The details on how it is being done are described here: https://blumareks.medium.com/discord-bot-on-your-voice-channel-9e5dc9814a8b

Step 6. (optional) Add Text-to-Speech to your voice Bot

You would like to add the Text-to-Speech services to your Bot to read the information in the Discord voice channel.

Step 7. Add a skill to run Bot-Backend-as-a-Service

First, let’s start a Serverless backend.

Use the following example to run a Serverless Action that analyses a picture and returns recognition tags.

  • sign in or sign up to IBM Cloud for your free LITE account

You can use this link to invoke IBM Cloud registration/signup/login page (this URL gives an author = me some brownie points): https://ibm.biz/Bd2CUa

  • Before anything else let’s provision Watson Visual Recognition service that you will consume in your Serverless skill.
Provision your service by selecting it in the Catalog, and creating a free service (one per account).

Now you are ready to make a note of your the APIkey 🔑

Just create a new API credential here:

Then you are ready to create your first Serverless Function (Serverless Skill)

  • From the menu (a hamburger) on the top left pick the Functions
Select Functions and Overview
  • Now you can start creating your first Serverless action
Start with Quickstart “Hello World” Template in Python

Now you can run the hello world example. Try to run your code — simply change the parameters, save the changes, and run the code — see the attached screenshots:

Then let’s get ready with your BBaaS code — we are going to recognize a picture with IBM Watson Visual Recognition.

from watson_developer_cloud import VisualRecognitionV3def main(params):
# init visual recognition library
apiKey = params['apiKey']
version = "2018-03-19"
visual_recognition = VisualRecognitionV3(version=version, iam_apikey=apiKey)
# get image url from params
# 20201124 changed from 'imageUrl' to 'img'
# due to a problem with the error in node.js serverless sdk
image_url = params['img']
# parse visual recognition return data for our tags
tags = ""
classifiedImages = visual_recognition.classify(url=image_url).get_result()
image = classifiedImages['images'][0]
classes = image['classifiers'][0]['classes']
for theClass in classes:
currentTag = theClass['class']
print(currentTag)
tags = tags + currentTag + ", "
result = {'classes': tags}
return result

Now you are ready to copy the following code and past it in the edit window.

Then add the Watson Visual Recognition apiKey to Parameters:

And the img to value

"img" and the value: "https://raw.githubusercontent.com/beemarie/ow-vr/master/images/puppy.jpg"

These are our results:

helloworld 1196 ms 11/20/2020, 07:21:42
Activation ID:
f7c9782ecf0b448289782ecf0b1482de
Results:
{
"classes": "puppy, dog, domestic animal, animal, Labrador retriever dog, retriever dog, golden retriever dog, pale yellow color, light brown color, "
}
Logs:
[
"2020-11-20T15:21:42.475648Z stdout: puppy",
"2020-11-20T15:21:42.475717Z stdout: dog",
"2020-11-20T15:21:42.475725Z stdout: domestic animal",
"2020-11-20T15:21:42.475732Z stdout: animal",
"2020-11-20T15:21:42.475737Z stdout: Labrador retriever dog",
"2020-11-20T15:21:42.475743Z stdout: retriever dog",
"2020-11-20T15:21:42.475748Z stdout: golden retriever dog",
"2020-11-20T15:21:42.475754Z stdout: pale yellow color",
"2020-11-20T15:21:42.475759Z stdout: light brown color"
]

Now let’s call it from our basic Bot from our code.

const Discord = require('discord.js');
const openwhisk = require('openwhisk')
const client = new Discord.Client();
const Apikey = process.env.apikey;
const options = { apihost: "us-south.functions.cloud.ibm.com", api_key: Apikey }
const ow = openwhisk(options)
const Token = process.env.token;
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
var text = 'no text';
const regexPrefix = new RegExp('ping*');
async function callServerlessAction(someText) {
try {

const name = '/<your-email-for-CF-Namespace>_dev/serverless-chatbot/picturebot';
const blocking = true;
const result = true;
//const params = {img: 'https://sportzbonanza.com/wp-content/uploads/2020/02/10566563q.jpg'}; //Robert Lewandowski - a famous Polish Soccer Player
const params = {img: someText}; //we hope someText is the url of an image
console.log("calling with params: " + params.img);
ow.actions.invoke({name, blocking, result, params})
.then(result => {
console.log("successful call");
console.log("text0: " + result); //an entire response from the service
text = JSON.stringify(result, null, 2);; //pass the value to the global variable
return JSON.stringify(result, null, 2);
})
.catch(err => {
console.log("unsuccessful call");
console.log(err);
return error.stringify;
});
} catch (error) {
console.error(error);
}
}
client.on('message', msg => {
if (regexPrefix.test(msg.content)) {
callServerlessAction(msg.content.substring(5));
setTimeout(function() {
return msg.reply("Watson analyzed: " + text); //Watson Vis Rec
}, 5000); //add some time for a cold start ?
};
});
client.login(Token);

Now simply build, ship, and run the Docker image:

First make sure that package.json Dockerfilehave all the required dependencies. These files should look like this:

$ more package.json
{
"dependencies": {
"discord.js": "^12.3.1",
"openwhisk": "^3.21.3"
}
}
$ more Dockerfile
FROM node:12
ENV NODE_CONTAINER_VERSION=1.0.0# Create directory for application
WORKDIR /data/bot-app
# Install dependencies
COPY package*.json ./
RUN npm installCOPY . .CMD [ "node", "index.js" ]
  • building an image:
docker build -t <your-docker-id>/node-serverlessbot:1.0 .Sending build context to Docker daemon  144.9kB
Step 1/7 : FROM node:12
---> 1f560ce4ce7e
Step 2/7 : ENV NODE_CONTAINER_VERSION=1.0.0
---> Using cache
---> 5bf5d13a4574
Step 3/7 : WORKDIR /data/bot-app
---> Using cache
---> 0e6e38f29ff9
Step 4/7 : COPY package*.json ./
---> Using cache
---> 19d1c4ff2682
Step 5/7 : RUN npm install
---> Using cache
---> b2d8931ff384
Step 6/7 : COPY . .
---> d653834ad3e7
Step 7/7 : CMD [ "node", "index.js" ]
---> Running in cb4d20a29914
Removing intermediate container cb4d20a29914
---> 98c8ad59d733
Successfully built 98c8ad59d733
Successfully tagged <your-docker-id>/node-serverlessbot:1.0
  • shipping an image:
docker push <your-docker-id>/node-serverlessbot:1.0
  • running a container:
discord-bot mareksadowski$ docker run -e token=”<your-Discord-bot-token>" -e apikey=”<your-Watson-Visual-Recognition-API-here>” -d <your-docker-id>/node-serverlessbot:1.0

now if you write ping with some URL to an image — the Discord Bot will provide you with the analysis see the message I used in the picture with the response:

ping https://sportzbonanza.com/wp-content/uploads/2020/02/10566563q.jpg

And the screenshot with the response:

Watson Visual Recognition in a Serverless skill in a Discord bot

The recording of setting up the backend is shown here: https://www.crowdcast.io/e/discord-chatbot-with-ibm-part3

Please checkout Lennart Frantzell’s and my book on Serverless Swift: https://www.apress.com/us/book/9781484258354

Thank you for reading this blog post/book. Follow me on Twitter:

--

--

Blumareks

I am a technology advocate for autonomous robots, AI, mobile and Internet of Things - with a view from both the enterprise and a robotics startup founder.