LINE BOT (Messaging API) development with API Gateway and Lambda (Python) [Part 2]

LINE BOT (Messaging API) development with API Gateway and Lambda (Python) [Part 2]

Introduction

[Part] and the main environmental construction in (https://qiita.com/w2or3w/items/1b80bfbae59fe19e2015), we put a simple example of just returns the "Hello!". In this second part, I would like to implement the following using line-bot-sdk. -String response ・ Acquisition of user information ・ Presentation of choices, acquisition of selected ones ・ Receive location information, send location information

Install line-bot-sdk

Since it is assumed to be deployed with Lambda, it must be installed in the same location as lambda_function.py. Let's do it in an appropriate folder (source in this case) so that the installed libraries can be zipped together.

|- source
   |- lambda_function.py

Install the library with pip.

$ cd source
$ pip install line-bot-sdk -t .

Deploy to Lambda

Zip the contents of the source folder and deploy the zip file to lambda.

$ cd source
$ zip -r ../lambda-package.zip *
$ aws lambda update-function-code --function-name sample-map-function-scraping --zip-file fileb://../lambda-package.zip

(* Please change sample-map-function-scraping to the target Lambda function name.)

If you check the function code of the Lambda console, you can see that it is deployed with the library included. image.png

Set the channel secret in the environment variable

I didn't use it in the first part, but I will use ** Channel Secret ** in "Channel Basic Settings" of the channel created by LINE Developpers. Please register it as the value of the key LINE_CHANNEL_SECRET in the environment variable.

Respond to a string

In the first part was a response to "Hello!" Without the use of a line-bot-sdk. I will write for comparison what happens when line-bot-sk is used.

lambda_function.py


import os
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage
)
LINE_CHANNEL_ACCESS_TOKEN   = os.environ['LINE_CHANNEL_ACCESS_TOKEN']
LINE_CHANNEL_SECRET         = os.environ['LINE_CHANNEL_SECRET']
LINE_BOT_API = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
LINE_HANDLER = WebhookHandler(LINE_CHANNEL_SECRET)

def lambda_handler(event, context):
    logger.info(event)
    signature = event["headers"]["X-Line-Signature"]
    body = event["body"]
    
    @LINE_HANDLER.add(MessageEvent, message=TextMessage)
    def on_message(line_event):
        LINE_BOT_API.reply_message(line_event.reply_token, TextSendMessage("Hello!"))
    
    LINE_HANDLER.handle(body, signature)
    return 0

It feels a little refreshing. It may seem difficult if you are not familiar with (or do not know) how to write using the library, but you will get used to it as you use it.

User information

What kind of user information can be obtained from LINE messages? I would like to confirm that.

    @LINE_HANDLER.add(MessageEvent, message=TextMessage)
    def on_message(line_event):
        profile = LINE_BOT_API.get_profile(line_event.source.user_id)
        logger.info(profile)
        LINE_BOT_API.reply_message(line_event.reply_token, TextSendMessage("Hello!"))

If you log the contents of profile and check it, it will be the following JSON.

{
    "displayName": "Your LINE name",
    "language": "ja",
    "pictureUrl": "https://profile.line-scdn.net/ch/v2/p/uxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/0000000000000",
    "userId": "U00000xxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

I was able to get the name registered in LINE, the URL of the profile image, the user ID, etc.

Choices

This is an implementation sample for presenting choices and getting selected ones. -When you receive the message "Choices", respond with some choices. ・ If selected, respond with "{Selected type} + has been selected!"

lambda_function.py


import os
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
    TemplateSendMessage, ButtonsTemplate,
    PostbackEvent
)
LINE_CHANNEL_ACCESS_TOKEN   = os.environ['LINE_CHANNEL_ACCESS_TOKEN']
LINE_CHANNEL_SECRET         = os.environ['LINE_CHANNEL_SECRET']
LINE_BOT_API = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
LINE_HANDLER = WebhookHandler(LINE_CHANNEL_SECRET)

def lambda_handler(event, context):
    logger.info(event)
    signature = event["headers"]["X-Line-Signature"]
    body = event["body"]

    #Event called when a text message is received
    @LINE_HANDLER.add(MessageEvent, message=TextMessage)
    def on_message(line_event):
        #Get user information
        profile = LINE_BOT_API.get_profile(line_event.source.user_id)
        logger.info(profile)

        message = line_event.message.text.lower()
        if message == 'Choices':
            LINE_BOT_API.reply_message(line_event.reply_token, make_select_message())
        else:
            LINE_BOT_API.reply_message(line_event.reply_token, TextSendMessage("Hello!"))

    #When selected from choices(postback)Event called
    @LINE_HANDLER.add(PostbackEvent)
    def on_postback(line_event):
        data = line_event.postback.data
        LINE_BOT_API.reply_message(line_event.reply_token, TextSendMessage("{0}You have selected!".format(data)))
    
    LINE_HANDLER.handle(body, signature)
    return 0

def make_select_message():
    return TemplateSendMessage(
        alt_text="Choices",
        template=ButtonsTemplate(
            title="Test of choice",
            text="Choose one from the bottom!",
            actions=[
                {
                    "type": "postback",
                    "data": "morning",
                    "label": "Morning"
                },
                {
                    "type": "postback",
                    "data": "noon",
                    "label": "Noon"
                },
                {
                    "type": "postback",
                    "data": "night",
                    "label": "Night"
                }
            ]
        )
    )

The result of the operation check is as follows. image.png

location information

An implementation for receiving and responding to location information. -Receives the "current position" and responds with "The latitude and longitude of that location is ({latitude}, {longitude})!". ・ When you receive the message "Lake Sanaru", respond to the location of Lake Sanaru.

lambda_function.py


import os
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
    TemplateSendMessage, ButtonsTemplate,
    PostbackEvent,
    LocationMessage, LocationSendMessage
)
LINE_CHANNEL_ACCESS_TOKEN   = os.environ['LINE_CHANNEL_ACCESS_TOKEN']
LINE_CHANNEL_SECRET         = os.environ['LINE_CHANNEL_SECRET']
LINE_BOT_API = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
LINE_HANDLER = WebhookHandler(LINE_CHANNEL_SECRET)

def lambda_handler(event, context):
    logger.info(event)
    signature = event["headers"]["X-Line-Signature"]
    body = event["body"]
    
    #Event called when a text message is received
    @LINE_HANDLER.add(MessageEvent, message=TextMessage)
    def on_message(line_event):
        #Get user information
        profile = LINE_BOT_API.get_profile(line_event.source.user_id)
        logger.info(profile)

        message = line_event.message.text.lower()
        if message == 'Choices':
            LINE_BOT_API.reply_message(line_event.reply_token, make_select_message())
        elif message == 'Lake Sanaru':
            LINE_BOT_API.reply_message(line_event.reply_token, make_sanaruko_location_message())
        else:
            LINE_BOT_API.reply_message(line_event.reply_token, TextSendMessage("Hello!"))

    #When selected from choices(postback)Event called
    @LINE_HANDLER.add(PostbackEvent)
    def on_postback(line_event):
        data = line_event.postback.data
        LINE_BOT_API.reply_message(line_event.reply_token, TextSendMessage("{0}You have selected!".format(data)))
        
    #Event called when location information is received
    @LINE_HANDLER.add(MessageEvent, message=LocationMessage)
    def on_location(line_event):
        latlon = "({0}, {1})".format(line_event.message.latitude, line_event.message.longitude)
        LINE_BOT_API.reply_message(line_event.reply_token, TextSendMessage("The latitude and longitude of that place is{0}is not it!".format(latlon)))

    LINE_HANDLER.handle(body, signature)
    return 0

def make_select_message():
    return TemplateSendMessage(
        alt_text="Choices",
        template=ButtonsTemplate(
            title="Test of choice",
            text="Choose one from the bottom!",
            actions=[
                {
                    "type": "postback",
                    "data": "morning",
                    "label": "Morning"
                },
                {
                    "type": "postback",
                    "data": "noon",
                    "label": "Noon"
                },
                {
                    "type": "postback",
                    "data": "night",
                    "label": "Night"
                }
            ]
        )
    )
    
def make_sanaruko_location_message():
    title = 'Lake Sanaru'
    address = '〒432-8002 5195 Tomitsuka-cho, Naka-ku, Hamamatsu-shi, Shizuoka'
    lat = 34.707433242045255
    lng = 137.68702025092614
    return LocationSendMessage(title=title, address=address, latitude=lat, longitude=lng)

"Location information" has a camera and image icon next to the LINE message input field, but it is in the menu that appears when you select the "+" icon next to it. image.png

The result of the operation check is as follows. image.png

Afterword

Actually, I was thinking of posting something like receiving an image, processing it, and returning it, but I quit. I was wondering if I could return the binary data as it is, but it seems that I need to publish it somewhere and return the URL, so I thought it would be a little long. I've stopped posting this article, but one day I'll write an article on this subject.

A year ago, I made a serverless web application "Mosaic" that detects faces and characters and applies a mosaic. Let's make a LINE BOT version of this. I'm thinking.

Recommended Posts

LINE BOT (Messaging API) development with API Gateway and Lambda (Python) [Part 2]
LINE BOT with Python + AWS Lambda + API Gateway
Made "Unofficial Apple Refurbished Product Introduction" BOT with LINE Messaging API (v2) + API Gateway + lambda (python)
[LINE Messaging API] Create parrot return BOT with Python
Amazon API Gateway and AWS Lambda Python version
I tried to make "Sakurai-san" a LINE BOT with API Gateway + Lambda
I made a LINE BOT with Python and Heroku
Read and write files with Slackbot ~ Bot development with Python ~
Quickly take a query string with API Gateway-> Lambda (Python)
I made LINE-bot with Python + Flask + ngrok + LINE Messaging API
Create API with Python, lambda, API Gateway quickly using AWS SAM
I made a Chatbot using LINE Messaging API and Python
[AWS] Create API with API Gateway + Lambda
I tried ChatOps with Slack x API Gateway x Lambda (Python) x RDS
[Python] I wrote a REST API using AWS API Gateway and Lambda.
I made a Chatbot using LINE Messaging API and Python (2) ~ Server ~
Create an automatic grade management app for Tenhou private room with LINE bot and Python Part 1
Create an automatic grade management app for Tenhou private room with LINE bot and Python Part 2
Create an automatic grade management app for Tenhou private room with LINE bot and Python Part ③
FM modulation and demodulation with Python Part 2
Easy REST API with API Gateway / Lambda / DynamoDB
Python calling Google Cloud Vision API from LINE BOT via AWS Lambda
How to make an artificial intelligence LINE bot with Flask + LINE Messaging API
[AWS SAM] Create API with DynamoDB + Lambda + API Gateway
View images on S3 with API Gateway + Lambda
Explosive speed with Python (Bottle)! Web API development
Get Gmail subject and body with Python and Gmail API
Continuation of multi-platform development with Electron and Python
Dynamic HTML pages made with AWS Lambda and Python
[Python] Using Line API [1st Creation of Beauty Bot]
Crawling with Python and Twitter API 1-Simple search function
[Python] A story about making a LINE Bot with a practical manned function on its own without using Salesforce [Messaging API]
Manage Python runtime packages and development environment packages with Poetry
[Python] Get user information and article information with Qiita API
Make ordinary tweets fleet-like with AWS Lambda and Python
Various memorandums when using sdk of LINE Messaging API with Python (2.7.9) + Google App Engine
[Super easy] Let's make a LINE BOT with Python.
How to operate Discord API with Python (bot registration)
I wrote a script to create a Twitter Bot development environment quickly with AWS Lambda + Python 2.7
Easy to use Nifty Cloud API with botocore and python
Try hitting the Twitter API quickly and easily with Python
AWS Amplify + API Gateway + Lambda + Python returns a normal response
I tried follow management with Twitter API and Python (easy)
[LINE Messaging API] Issue channel access token v2.1 in Python
Specification generation and code generation in REST API development (Python edition)
Image processing with Python (Part 2)
Programming with Python and Tkinter
Encryption and decryption with Python
Studying Python with freeCodeCamp part1
Use Trello API with python
Bordering images with python Part 1
Operate TwitterBot with Lambda, Python
Python and hardware-Using RS232C with Python-
Scraping with Selenium + Python Part 1
AWS CDK-Lambda + API Gateway (Python)
Use Twitter API with Python
Studying Python with freeCodeCamp part2
Image processing with Python (Part 1)
Web API with Python + Falcon
Solving Sudoku with Python (Part 2)
Image processing with Python (Part 3)