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!"
In this article, we will create a LINE Bot that returns parrots. The flow of the program is as follows. (** Service ** is the program created this time)
First, let's create a template for the project. If you already have a template or want to incorporate it into your existing code, proceed to the next chapter.
Terminal
$ bundle init
Generate a Gemfile with the bundle init
command.
And let's add the following gem.
Gemfile
#Omission
gem "sinatra"
gem "sinatra-contrib"
gem "dotenv"
gem "line-bot-api"
After completing the description, install it with the bundle
command.
Terminal
$ bundle
Next, we will create the core file. This time, the file name is ʻapp.rb`.
app.rb
require 'bundler/setup'
Bundler.require
require 'sinatra/reloader' if development?
get '/' do
"Hello world!"
end
Now, let's run it and test its operation.
Terminal
$ ruby app.rb -o 0.0.0.0
Enter the command to start the program. Sinatra's default port number is 4567, so let's go to http: // localhost: 4567 /. If "Hello world!" Is displayed, Sinatra's environment construction is complete! (The port numbers in the screenshots are different because you are biting Docker, so don't worry too much> <)
https://developers.line.biz/ja/ Go to and log in. If you normally use LINE, you can log in with a QR code.
When you log in, you should see a screen like the one below. For the time being, you can change the language from the button at the bottom right, so it's easier to use Japanese.
Whenever you develop a LINE Bot, the words "provider" and "channel" come up. These can be roughly explained
--Provider: Developer account --Channel: Bot account
It means that · · · Providers are created in units such as companies, individuals, and groups of developers, and channels belong to one provider.
So let's create a provider first. When you click "Create new provider", a screen for entering the provider name will appear, so enter the provider name you like.
The provider name you enter here will be ** published ** as the author of the bot. You should write down your real name. Press the create button to create the provider.
Next, let's create a channel that will be a bot account. The channel used by the bot is "Messaging API", so click the Messaging API.
The setting screen for the newly created channel will appear. Let's fill in the necessary contents.
item | Contents |
---|---|
Channel type | Messaging API |
Provider | What I made earlier |
Channel icon | You don't have to set it now |
Channel name | Bot name |
Channel description | Bot description |
Large industry | Bot genre |
Small industry | Detailed genre of bot |
mail address | The email address where you will be contacted about the bot. It's a good idea to use an email address that you can contact. |
Privacy policy URL | You don't have to set it now |
Terms of Service URL | You don't have to set it now |
After agreeing to the required terms, press the create button to create the channel.
Now that you have the channels you need for your bot, let's write the keys and secrets to the .env file. You can write it directly in the program, but it's not so good considering security.
.env
LINE_CHANNEL_ID=xxxxxxxxxx
LINE_CHANNEL_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
LINE_CHANNEL_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Channel ID and channel secret are "Channel basic settings" The channel token is listed in the "Messaging API Settings" under the name "Channel Access Token (Long Term)". If it is not displayed, press the publish button to publish it.
Write Dotenv.load under require so that the variables described in .env can be used in the program.
app.rb
require 'bundler/setup'
Bundler.require
require 'sinatra/reloader' if development?
Dotenv.load # <-Postscript
get '/' do
"Hello world!"
end
Webhook is a mechanism to have the content of the event POSTed to the URL set in advance when the event occurs in the service of the other party (LINE in this article).
For example, if you set the URL / callback
of your service to the LINE channel, you can have / callback
POST the content of the message when a message arrives on the channel.
However, since it needs to be a URL that can be accessed from the LINE server, it will not work properly when the service is not actually published. For example, localhost: 4567 under development is a URL that can only be accessed from your own PC, so even if a message comes with localhost: 4567 / callback
set, localhost: 4567 / callback
will not be called.
Because of this specification, you basically need to deploy every time you develop a LINE Bot. If you open the port, you can save the trouble of deploying each time, but there is a security risk, so we will not introduce it here.
It's basically the same as the README on GitHub, but the image processing is omitted and the code is simple. https://github.com/line/line-bot-sdk-ruby
app.rb
require 'bundler/setup'
Bundler.require
require 'sinatra/reloader' if development?
Dotenv.load
# ======Postscript from here======
def client
@client ||= Line::Bot::Client.new { |config|
config.channel_id = ENV["LINE_CHANNEL_ID"]
config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
}
end
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
# ======Postscript up to here======
get '/' do
"Hello wolrd!"
end
I will explain the code below.
def client
@client ||= Line::Bot::Client.new { |config|
config.channel_id = ENV["LINE_CHANNEL_ID"]
config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
}
end
This is the code to enable the "client" to operate the LINE Bot (this is a function of line-bot-api
).
You can create a client with Line :: Bot :: Client.new
, but it is implemented like this because one client is enough for one service.
||=By using operators@When the client is emptyLine::Bot::Client.new
And pass it on.@If the client is already in, pass it. The processing is realized.
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
The post'/ callback'do
block is a bit long, so I'll explain it separately.
body = request.body.read
just assigns the sent data to the body variable.
After the signature, we check whether the data sent is really from the LINE server.
The data sent from the LINE server always contains something called "HTTP_X_LINE_SIGNATURE", and you can check whether it is the data sent from the LINE server by looking at the contents.
Checking if it is a LINE server is implemented in line-bot-api
and can be used through the client created earlier.
The verification process is executed in the part called client.validate_signature (body, signature)
.
This is an important code that checks if a malicious person is spoofing the LINE server and sending a message.
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
In ʻevents = client.parse_events_from (body)`, the sent data is converted into a form that is easy to handle with ruby. The result of the conversion is an array of events, as you can see from the name events.
events.each do |event|
Is processing multiple events one by one. This is because multiple events may be sent at the same time.
ʻIf event.is_a? (Line :: Bot :: Event :: Message)` checks if the event type is Message. Non-message events include "Add Friend" and "Unblock".
ʻIf event.type === Line :: Bot :: Event :: MessageType :: Text` confirms that the message type is text. Non-text message types include images, videos, and stamps.
In other words, the code from the top 4 lines is used to "analyze the transmitted data and narrow down only the text message".
Next, let's look at the code inside the if statement.
message = {
type: 'text',
text: event.message['text']
}
client.reply_message(event['replyToken'], message)
The top four lines assemble the message to send to the LINE server, and the last one line sends the reply. event ['replyToken'] is the reply token included in the event.
At the end, I wrote " OK "
, but it follows the rule of LINE Bot API that it is necessary to return the correct response if the process succeeds normally. It's okay to return anything.
Now that the code is complete, let's run it! Unfortunately, as I explained earlier, it does not work when executed locally. So, this time I will deploy to Heroku.
I will omit the details of deploying to heroku, but let's create only Procfile.
Procfile
web: bundle exec ruby app.rb -o 0.0.0.0 -p $PORT
Terminal
$ git init
$ git add -A
$ git commit -m "first commit"
$ heroku create
$ git push heroku master
After deploying, let's open the application. If "Hello wolrd!" Is displayed, the deployment is complete!
Go to the LINE Developers site and go to the channel settings screen.
Open Messaging API Settings and click Edit Webhook URL.
A box for entering the URL will appear, so enter URL + / callback
you just deployed and press the update button.
For example, the deployed URL
https://xxxxxxx-yyyyyy-zzzzz.herokuapp.com
If so
https://xxxxxxx-yyyyyy-zzzzz.herokuapp.com/callback`
It will be.
After that, let's check the use of Webhook.
`![Screenshot 2020-07-12 4.14.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672451/d25d1f73-bcee-6424-c5f3 -0b65709b2414.png)
You can check the operation of the server by pressing the verification button. If it is displayed as successful, there is no problem.
Also, Bot messages cannot be sent at this time because auto-answer messages are enabled. So disable auto attendant.
Click the Edit Response Message button in the Messaging API settings. Then, a page called response settings will be displayed, so you can see the detailed settings below.
--Turn response message ** off ** --Webhook ** on **
Set.
Now you are ready to use the webhook.
Well, everything is ready! Add your bot to your friends and send a message! There is a QR code in "Messaging API settings", so let's read it with LINE. You should be able to make friends with the bot you made.
If you can make friends, send a message. If you get the same message you sent, you're successful! Thank you for your support!
In this article, I made a bot that returns a parrot of the sent message. It's very simple, but it contains a lot of important code that is essential for making bots, so it's a good idea to familiarize yourself with it!
The next article is here
Recommended Posts