11
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

LINE BOTを使って疑似彼女を錬成するレシピ

Last updated at Posted at 2021-11-12

はじめに

最近寒くなってきましたね〜、そしてもうすぐクリスマス!
世のカップルを爆撃するのを楽しみにしております ☆ wkwk

depositphotos_320979774-stock-photo-closeup-of-red-baubles-hanging.jpg

そんな寂しい僕のお供としてLINE BOTを作ってみましたので、今年のクリスマスは一緒に過ごそうと思います ♡

紹介すること・しないこと

紹介すること

  • アプリケーションの構成
  • BOTの仕様
  • DB設計
  • プログラム、及びその解説
  • 採用PR (ぜひ最後のページまで見ていって下さい!)

紹介しないこと
LINE DeveloperサイトでのLINEアカウントの作り方は省略させて下さい。すいません > <

構成

自前で用意したサーバがLINE BOTのサーバからHTTPでBodyを受け取ります。
その後、gRPC経由でGoにリクエストを投げテキストを加工しPHPに返しています。
linebot (3).png

BOTの仕様

  • 特定のキーワードを含むメッセージには、専用のメッセージで返信する
  • それ以外のメッセージには、ランダムで用意したメッセージを返す

公式LINEアカウントあるあるですね。

DB設計

ざっくりとしたER図ですが以下のように作ってます。
PHPがDBと接続することはなく、GoがCRUDを担います。
※ created_at等々の記述は省略しています。

linebot_er.drawio.png

各テーブルの解説

accounts

  • line_id ... LINE BOTサーバーから送られてきたUserIDの保存場所
  • last_action_date ... LINEユーザの最終アクション日時をログっています

message_logs

  • account_id ... accountsテーブルの外部キー
  • text ... LINEから送られてきたメッセージの保存場所

responses

  • match ... 特定のキーワードを保存
    LINEから送られてきたメッセージがmatchカラムと部分マッチした場合にtextカラムの値を返す
  • text ... 特定のキーワードが含まれているケースでの返信に使用するテキスト

実装したコード

PHP

index.php
<?php
require('vendor/autoload.php');

use LINE\LINEBot\HTTPClient\CurlHTTPClient;
use LINE\LINEBot;

$channel_access_token = getenv('CHANNEL_ACCESS_TOKEN');
$channel_secret = getenv('CHANNEL_SECRET');

class LinebotService
{
  private $client;

  function __construct()
  {
    $this->client = new Akame\LinebotClient(getenv('GRPC_HOST'), [
      'credentials' => Grpc\ChannelCredentials::createInsecure(),
    ]);
  }

  function reply_message_request(string $line_id, string $text): string
  {
    $request = new Akame\ReplyMessageRequest();
    $request->setLineId($line_id);
    $request->setText($text);
    list($response, $status) = $this->client->ReplyMessage($request)->wait();
    if ($status->code !== Grpc\STATUS_OK) {
      echo "ERROR: " . $status->code . ", " . $status->details . PHP_EOL;
      exit(1);
    }
    return $response->getMessage();
  }
}

$http_client = new CurlHTTPClient($channel_access_token);
$bot = new LINEBot($http_client, ['channelSecret' => $channel_secret]);

$line_service = new LinebotService();
$events = $bot->parseEventRequest(file_get_contents('php://input'), $_SERVER['HTTP_X_LINE_SIGNATURE']);
foreach ($events as $event) {
  $bot->replyText($event->getReplyToken(), $line_service->reply_message_request($event->getUserId(), $event->getText()));
}

コードの解説

以下でgRPCにリクエストする値をセットしています。

$request->setLineId($line_id);
$request->setText($text);

{line_id: "xxxx", "text": "Hello"}ってリクエストをイメージしてもらうとわかりやすいかもです。

envはdirenvからセットしています。
https://github.com/direnv/direnv


Go

message.go
package services

import (
	m "akame/app/models"
	pb "akame/protobuf"
	"context"
)

type MessageService struct {
	pb.UnimplementedLinebotServer
}

func (s *MessageService) ReplyMessage(ctx context.Context, in *pb.ReplyMessageRequest) (*pb.ReplyMessageResponse, error) {
	account := &m.Account{}
	account_row := account.CreateAccount(in.GetLineId())

	messageLog := &m.MessageLog{}
	messageLog.Logger(int(account_row.ID), in.GetText())

	response := &m.Response{}

	return &pb.ReplyMessageResponse{Message: response.Reply(in.GetText())}, nil
}

コードの解説

// アカウントの作成をしています。
account.CreateAccount(in.GetLineId())
// メッセージをログとして残しています。
messageLog.Logger(int(account_row.ID), in.GetText())
// 返信用メッセージのテキストを返す。
response.Reply(in.GetText())

返信用のランダムテキストはDBじゃなくて、レスポンスモデルに配列で持っています。
(上のコードにないですが)

response.go
var replyPattern = []string{
	"今が1番幸せ", "いつもありがとう", "あなたと一緒にいると楽しい", "早く会いたいな",
	"2人だけの秘密ね",
}

Seed

responsesテーブルのデータを事前に入れておきます。

migrate/sql/000004_seed_respose.up.sql
INSERT INTO `responses`(`match`, `text`)
  VALUES ("愛してる", "私も愛してる"), ("かわいいね", "もうっ、恥ずかしいよ //");
migrate/sql/000004_seed_respose.down.sql
TRUNCATE responses;

go-gormigrateを使用しています。

彼女と会話してみる

スクリーンショット 2021-11-12 11.48.32.png

どうやら相思相愛のようです > <

あとがき

BOTから返信を貰うためにLINEにテキスト打つ時が一番キツかったですねw

気づいたら、今年ももうあと少しですね〜。
世の中的に色々あって大変でしたけど、落ち着いて来ているので楽しいクリスマス・年末年始を過ごせそうです!

採用PR

大規模サイトので開発やマイクロサービス化・二次元コンテンツに興味がある、もしくはチャレンジしてみたいという方は是非一緒に働きましょう!

11
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?