Let's make a LINE Bot with Ruby + Sinatra --Part 2

Hello. In this series, I used Ruby and Sinatra multiple times.

--Send the ISBN code on the back of the book to search and display the image of the book --You can record the book and refer to it later.

I would like to make a LINE Bot called "Honmemo!"

This article is a sequel to Part 1. If you haven't read it yet, please read it!

0. What to make in this article

In this article, I will write a program that returns search results using an API that actually returns book information. The flow of the program is as follows.

linebot.png

0_1. Introduction of book search API

This time, we will use "openBD". openBD is an API operated by Carlyl Co., Ltd. and publisher dot com, and you can get basic information of books and shadows (cover photo).

https://api.openbd.jp/v1/get?isbn=9784873113944

If you pass isbn like this, an array of book data will be returned in JSON format. You can also specify multiple books by separating them with commas. Detailed API specifications can be found in OpenBD Bibliographic API Data Specifications (v1).

Basically, you can look inside the summary.

0_2. Trivia: What is ISBN?

ISBN is an abbreviation for International Standard Book Number, which is a 10- or 13-digit number uniquely attached to any book. It's on the back cover of most books and is also a barcode. If it is an old book, it may be listed only in the colophon. Books have two-tiered barcodes because they are separated by ISBN code and book JAN code (product code).

1. Call the openBD API

Create a function to get as follows (you don't have to move the comment).

def getBookByISBN(isbn)
  return nil if !isbn.match(/^(\d{10}|978\d{10})$/) #Returns nil if not in ISBN format

  uri = URI.parse("https://api.openbd.jp/v1/get?isbn=" + isbn)
  res = Net::HTTP.get_response(uri) #Call the API
  return nil if res.code != "200" #Returns nil if an error occurs
  
  books = JSON.parse(res.body) #Read API results as JSON format
  return nil if books.length == 0 #Returns nil if the number of applicable books is 0
  
  return books[0] #Returns the first of the API results
end

2. Let's display the book search results on the Web

Made last time

get '/' do
  "Hello wolrd!"
end

Let's divert. This time, I would like to make it a specification that returns the book name when /? Isbn = 978xxxxxxxxxx is accessed.

get '/' do
  book = getBookByISBN(params['isbn'])
  return book['summary']['title']
end

Now, if you can write so far, let's access http: // localhost: {PORT} /? Isbn = {ISBN} of your favorite book. If the name of the book comes out, it's a success! スクリーンショット 2020-07-26 0.22.12.png

3. Add a function to LINE Bot to return the name of the book

Recall the LINE Bot code I wrote last time.

post '/callback' do
  body = request.body.read

  signature = request.env['HTTP_X_LINE_SIGNATURE']
  unless client.validate_signature(body, signature)
    error 400 do 'Bad Request' end
  end

  events = client.parse_events_from(body)
  events.each do |event|
    if event.is_a?(Line::Bot::Event::Message)
      if event.type === Line::Bot::Event::MessageType::Text
        message = {
          type: 'text',
          text: event.message['text']
        }
        client.reply_message(event['replyToken'], message)
      end
    end
  end

  "OK"
end

The most important of these

message = {
  type: 'text',
  text: event.message['text']
}
client.reply_message(event['replyToken'], message)

It is the part of. This is the process to be performed when a "text message" arrives from the user. You can get the text data sent by ʻevent.message ['text']. You can send a reply with client.reply_message (event ['replyToken'], message)`.

Let's improve this code a bit so that we can search for books. ʻIf event.type === Line :: Bot :: Event :: MessageType :: Rewrite the contents from Text to ʻend as follows.

book = getBookByISBN(event.message['text']) #Search for ISBN and assign book information to a variable
messages = [] #Variables for the message to reply

if book.nil?
  #If the book is empty
  messages.push({
    type: 'text',
    text: 'The book was not found'
  })
else
  #If a book is found
  messages.push({
    type: 'text',
    text: book['summary']['title']
  })
end

client.reply_message(event['replyToken'], messages)

Until now, client.reply_message was passed an object with type and text called message, but this time I tried to pass an array containing the message object. This will allow you to reply to multiple messages. It will be used when creating a function to reply the cover image that will appear in the next chapter!

3_1. Let's deploy

Now, the addition of LINE Bot functions is complete! I'd like to try it immediately, but as I explained last time, I can't test it unless I deploy it. Enter the following command to deploy.

$ git add -A
$ git commit -m "add search book"
$ git push heroku master

After the deployment is complete, let's send the ISBN to the LINE Bot. If the book name is returned as shown in the screenshot below, you are successful!

IMG_0541.PNG

4. Add a function to return the image of the book to LINE Bot

Next, let's add a function to return the cover image of the book.

The cover image can be obtained with book ['summary'] ['cover']. However, not all books have images, so you need to check for them.

So, let's write as follows.

book = getBookByISBN(event.message['text']) #Search for ISBN and assign book information to a variable
messages = [] #Variables for the message to reply

if book.nil?
  #If the book is empty
  messages.push({
    type: 'text',
    text: 'The book was not found'
  })
else
  #If a book is found
  if !book['summary']['cover'].empty? 
    #If there is a cover image
    messages.push({
      type: 'image',
      originalContentUrl: book['summary']['cover'],
      previewImageUrl: book['summary']['cover'],
    })
  end
  messages.push({
    type: 'text',
    text: book['summary']['title']
  })
end

client.reply_message(event['replyToken'], messages)

4_1. Let's deploy

This completes the cover image reply function! Enter the following command to deploy.

$ git add -A
$ git commit -m "add cover image"
$ git push heroku master

After the deployment is complete, let's send the ISBN to the LINE Bot. If the cover image and book name are returned as shown in the screenshot below, you are successful!

IMG_0542.PNG

4_2. Digression

It also does a simple error check, so if you send an ISBN that doesn't exist, you'll get an error back.

image.png

Also, in the case of a book without a cover image, only the title should be returned like this.

image.png

5. Summary

In this article, I made a bot that returns the title and image of the book based on the ISBN sent! It contains useful parts for making bots, such as sending multiple messages, so I think it's useful to remember!

List of serialized articles

  1. Let's make a LINE Bot with Ruby + Sinatra --Part 1 --Let's make a bot that returns parrots
  2. Let's make a LINE Bot with Ruby + Sinatra --Part 2 --Search for books and return information ← Imakoko
  3. Let's make a LINE Bot with Ruby + Sinatra --Part 3 --Let's record the searched books (planned)

Recommended Posts

Let's make a LINE Bot with Ruby + Sinatra --Part 2
Let's make a LINE Bot with Ruby + Sinatra --Part 1
Make a typing game with ruby
Let's make a book management web application with Spring Boot part1
Let's make a Christmas card with Processing!
Make a family todo list with Sinatra
Let's make a book management web application with Spring Boot part3
Let's make draw poker with ruby ~ Preparation ~
Let's make a book management web application with Spring Boot part2
Make a family todo list with Sinatra
Extract a part of a string with Ruby
Let's make draw poker with ruby ~ test-unit preparation ~
Let's make a search function with Rails (ransack)
I made a LINE bot with Rails + heroku
Easy to make LINE BOT with Java Servlet
How to make LINE messaging function made with Ruby
[Java basics] Let's make a triangle with a for statement
Learning Ruby with AtCoder 13 How to make a two-dimensional array
Let's make a simple API with EC2 + RDS + Spring boot ①
Easy to make LINE BOT with Java Servlet Part 2: I tried image messages and templates
[Rails] Push transmission with LINE Bot
Make a digging maze with Ruby2D
I want to make a button with a line break with link_to [Note]
Make a slideshow tool with JavaFX
Make a garbage reminder with line-bot-sdk-java
Make a list map with LazyMap
Let's go with Watson Assistant (formerly Conversation) ② Make a hotel reservation chatbot
If you want to make a zip file with Ruby, it's rubyzip.
[LINE BOT] I made a ramen BOT with Java (Maven) + Heroku + Spring Boot (1)
Make a note of Ruby keyword arguments
Let's make draw poker with ruby-Implementation 1 (card)-
Let's make draw poker with ruby-Implementation 4 (Deck)-
Draw a graph with Sinatra and Chartkick
How to make a Discord bot (Java)
I made a risky die with Ruby
Make a login function with Rails anyway
[docker] [nginx] Make a simple ALB with nginx
Let's make draw poker with ruby-Implementation 3 (player)-
[Java] Let's make a DB access library!
Let's make draw poker with ruby-Implementation 2 (role)-
Let's make an error screen with Rails
[LINE @] I tried to make a Japanese calendar Western calendar conversion BOT [Messaging API]
I tried to make a machine learning application with Dash (+ Docker) part3 ~ Practice ~
Let's make a calculator application with Java ~ Create a display area in the window
I tried to make a simple game with Javafx ① "Let's find happiness game" (unfinished)
line bot
Let's get started with Java-Create a development environment ②
Let's get started with Java-Create a development environment ①
AtCoder Beginner Contest 169 A, B, C with ruby
Let's create a timed process with Java Timer! !!
Conversation status (context) management (session management?) With LINE BOT
Let's make a shopping site using stripe! (Purchase)
Make Java Stream line breaks nice with eclipse
Make System.out a Mock with Spock Test Framework
Deploy Line bot with rails5 + Docker + Heroku Note
I made a portfolio with Ruby On Rails
I tried to make a simple game with Javafx ① "Let's find happiness game" (unfinished version ②)
A note about getting stuck when making a parrot return LINE bot on Heroku + Sinatra
Let's make a circuit breaker for back-end service using Actuator of Spring Boot (Part 1)