Try โ€‚โ€‰HackMD

Messenger Bot: Example Bot Using an External API

tags: MessengerBot

Besides from webscraping, you can also obtain data from external APIs. In this workshop, I'll making a bot that integrates with the Giphy API to send a gif with my input.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’


The Process

Goal: Input a keyword and output a related gif.

Since I want to send a image back to the user, I'll probably need:

  • send_image()
  • Image url returned by the API

Intro to APIs

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’


Using APIs

  1. Select an API
  2. Read the API Documentation
  3. Make a request
  4. Do stuff with the response

Quick note: Some APIs might require special authentication steps such as obtaining an API key or an access token. Read the API documentation for access requirements.


Let's jump right in!

The first step is already taken care of for you (by me). We'll be using the Giphy API to fetch gifs based on a user's input.

Onto step 2: reading the API documentation!

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’

Head over to https://developers.giphy.com/docs/api#quick-start-guide to get started.


Step 2: Docs, Docs, Docs ๐Ÿ“„

Looks like Giphy has a Search Endpoint, which returns gifs based on a certain query string. Just what we need!

Giphy requires users to obtain an API key (free!) in order to make requests to its API.

  1. Go to https://developers.giphy.com/dashboard/?create=true and create a new App (make sure to select API, not SDK)

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’

  1. Make a new variable in your .env file

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’

  1. Load the env variable to use in your code
GIPHY_API_KEY = os.environ.get("GIPHY_API_KEY")

Giphy has a neat API explorer tool you can play around with to try the API out: https://developers.giphy.com/explorer/

This endpoint can be broken down like so:

API host: api.giphy.com

Path: /v1/gifs/search

Parameters: ?q=YOUR_INPUT&api_key=YOUR_API_KEY&limit=1

Here's also an example request in a code sample:
https://developers.giphy.com/docs/resource/#code-examples


Search Query

The request to send to Giphy looks like this:
http://api.giphy.com/v1/gifs/search?q=YOUR+SEARCH+HERE&api_key=YOUR_API_KEY&limit=5

From the Echo Bot, we know we can get the user's input using messaging_event['message']['text']

Now, we only need to process that string and insert it into the query.

# This splits the input string into a list
input = messaging_event['message']['text'].lower().split()

# This turns the list back into a string but separated by +
search_query = "+".join(input)

Step 3: Making the Request

# Base url for GIPHY search endpoint
giphy_url = "http://api.giphy.com/v1/gifs/search?q={input}&api_key={api_key}&limit={limit}"

# Make the request to get the page
query = giphy_url.format(input=search_query, api_key=GIPHY_API_KEY, limit=1)

# Use requests library to make the request
response = requests.get(query)

# Print out the response as JSON
pprint(response.json())

Step 4: Parsing the JSON response

The JSON response will look something like this:

{ "data": [ { "type": "gif", "id": "d3erWmTEGXoiYVgY", "url": "https://giphy.com/gifs/redandhowling-funny-cute-d3erWmTEGXoiYVgY", "slug": "redandhowling-funny-cute-d3erWmTEGXoiYVgY", "bitly_gif_url": "http://gph.is/2ni2FXr", "bitly_url": "http://gph.is/2ni2FXr", "embed_url": "https://giphy.com/embed/d3erWmTEGXoiYVgY", "username": "redandhowling", "source": "https://shop.redandhowling.com/", "title": "Tired Good Morning GIF by Red & Howling", "rating": "g", "content_url": "", "source_tld": "shop.redandhowling.com", "source_post_url": "https://shop.redandhowling.com/", "is_sticker": 0, "import_datetime": "2018-01-27 06:14:05", "trending_datetime": "2019-07-25 15:15:02", "images": { "original": { "height": "360", "width": "480", "size": "273098", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy.gif", "mp4_size": "79611", "mp4": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy.mp4?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy.mp4", "webp_size": "125630", "webp": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy.webp?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy.webp", "frames": "18", "hash": "2ec1024afcabfc64aae3f82107427376" }, "downsized": { "height": "360", "width": "480", "size": "273098", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy.gif" }, "downsized_large": { "height": "360", "width": "480", "size": "273098", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy.gif" }, "downsized_medium": { "height": "360", "width": "480", "size": "273098", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy.gif" }, "downsized_small": { "height": "360", "width": "480", "mp4_size": "79611", "mp4": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy-downsized-small.mp4?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy-downsized-small.mp4" }, "downsized_still": { "height": "360", "width": "480", "size": "273098", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy_s.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy_s.gif" }, "fixed_height": { "height": "200", "width": "267", "size": "102935", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200.gif", "mp4_size": "33514", "mp4": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200.mp4?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200.mp4", "webp_size": "70496", "webp": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200.webp?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200.webp" }, "fixed_height_downsampled": { "height": "200", "width": "267", "size": "54229", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200_d.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200_d.gif", "webp_size": "52392", "webp": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200_d.webp?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200_d.webp" }, "fixed_height_small": { "height": "100", "width": "134", "size": "42936", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/100.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=100.gif", "mp4_size": "11890", "mp4": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/100.mp4?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=100.mp4", "webp_size": "28756", "webp": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/100.webp?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=100.webp" }, "fixed_height_small_still": { "height": "100", "width": "134", "size": "5512", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/100_s.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=100_s.gif" }, "fixed_height_still": { "height": "200", "width": "267", "size": "18942", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200_s.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200_s.gif" }, "fixed_width": { "height": "150", "width": "200", "size": "69674", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200w.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200w.gif", "mp4_size": "22266", "mp4": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200w.mp4?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200w.mp4", "webp_size": "48262", "webp": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200w.webp?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200w.webp" }, "fixed_width_downsampled": { "height": "150", "width": "200", "size": "35675", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200w_d.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200w_d.gif", "webp_size": "37748", "webp": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200w_d.webp?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200w_d.webp" }, "fixed_width_small": { "height": "75", "width": "100", "size": "29834", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/100w.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=100w.gif", "mp4_size": "8338", "mp4": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/100w.mp4?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=100w.mp4", "webp_size": "21074", "webp": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/100w.webp?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=100w.webp" }, "fixed_width_small_still": { "height": "75", "width": "100", "size": "3858", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/100w_s.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=100w_s.gif" }, "fixed_width_still": { "height": "150", "width": "200", "size": "13301", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/200w_s.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=200w_s.gif" }, "looping": { "mp4_size": "943174", "mp4": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy-loop.mp4?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy-loop.mp4" }, "original_still": { "height": "360", "width": "480", "size": "48284", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy_s.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy_s.gif" }, "original_mp4": { "height": "360", "width": "480", "mp4_size": "79611", "mp4": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy.mp4?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy.mp4" }, "preview": { "height": "284", "width": "378", "mp4_size": "25753", "mp4": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy-preview.mp4?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy-preview.mp4" }, "preview_gif": { "height": "154", "width": "205", "size": "49562", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy-preview.gif?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy-preview.gif" }, "preview_webp": { "height": "178", "width": "238", "size": "46600", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy-preview.webp?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy-preview.webp" }, "hd": { "height": "810", "width": "1080", "mp4_size": "316666", "mp4": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/giphy-hd.mp4?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=giphy-hd.mp4" }, "480w_still": { "height": "360", "width": "480", "size": "273098", "url": "https://media0.giphy.com/media/d3erWmTEGXoiYVgY/480w_s.jpg?cid=50ac883419blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&rid=480w_s.jpg" } }, "user": { "avatar_url": "https://media4.giphy.com/avatars/redandhowling/KBya1PlSw5HO.jpg", "banner_image": "https://media4.giphy.com/headers/redandhowling/bluYWDAjbKPK.gif", "banner_url": "https://media4.giphy.com/headers/redandhowling/bluYWDAjbKPK.gif", "profile_url": "https://giphy.com/redandhowling/", "username": "redandhowling", "display_name": "Red & Howling", "description": "Celebrating our love of animals through super-cute cartoons and animations. shop.redandhowling.com", "instagram_url": "https://instagram.com/redandhowling", "website_url": "https://redandhowling.com/", "is_verified": true }, "analytics_response_payload": "e=Z2lmX2lkPWQzZXJXbVRFR1hvaVlWZ1kmZXZlbnRfdHlwZT1HSUZfU0VBUkNIJmNpZD01MGFjODgzNDE5Ymx2bW1qd21obmwwZmgyd2h2bzIwcDZ4NmlnZXV3bDlhY3B4ZnE", "analytics": { "onload": { "url": "https://giphy-analytics.giphy.com/simple_analytics?response_id=19blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&event_type=GIF_SEARCH&gif_id=d3erWmTEGXoiYVgY&action_type=SEEN" }, "onclick": { "url": "https://giphy-analytics.giphy.com/simple_analytics?response_id=19blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&event_type=GIF_SEARCH&gif_id=d3erWmTEGXoiYVgY&action_type=CLICK" }, "onsent": { "url": "https://giphy-analytics.giphy.com/simple_analytics?response_id=19blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq&event_type=GIF_SEARCH&gif_id=d3erWmTEGXoiYVgY&action_type=SENT" } } } ], "pagination": { "total_count": 19754, "count": 1, "offset": 0 }, "meta": { "status": 200, "msg": "OK", "response_id": "19blvmmjwmhnl0fh2whvo20p6x6igeuwl9acpxfq" } }

Parsing the gif url:

# Check if request was successful
if (response.status_code == 200):
    # Get the first gif from the list returned
    gif_obj = response.json()['data'][0]
    
    # Get the .gif url of the gif
    gif_url = gif_obj['images']['original']['url']

Return the image

# Send image link
messager.send_image(sender_id, gif_url)

Test it out!

Message your bot a word or phrase (i.e "dog") and get a gif back!

Challenge: Modify the code such that a random gif is returned (instead of always returning the same gif)


Full Code:

# Loads environment variable GIPHY_API_KEY = os.environ.get("GIPHY_API_KEY") # This splits the input string into a list input = messaging_event['message']['text'].lower().split() # This turns the list back into a string but separated by + search_query = "+".join(input) # Base url for GIPHY search endpoint giphy_url = "http://api.giphy.com/v1/gifs/search?q={input}&api_key={api_key}&limit={limit}" # Make the request to get the page query = giphy_url.format(input=search_query, api_key=GIPHY_API_KEY, limit=1) # Use requests library to make the request response = requests.get(query) # Check if request was successful if (response.status_code == 200): # Get the first gif from the list returned gif_obj = response.json()['data'][0] # Get the url of the gif gif_url = gif_obj['images']['original']['url'] # Send image link messager.send_image(sender_id, gif_url)

That's it!

That's it for the intro to API workshop! You can play around with the Giphy API and do some cooler stuff, or check out other APIs you want to integrate into your bot.

Here are some fun APIs to explore: