何気に重要かも？LINE Messaging APIのテキストメッセージv2を調べてみた


こんにちは、のびすけです。

しれっと？リリースされていたテキストメッセージv2ってなんだ？ってところを調べてみます。

https://developers.line.biz/ja/news/2024/10/30/text-message-v2/

## テキストメッセージv2って？

> Messaging APIにおいて、新しいメッセージオブジェクトとしてテキストメッセージ（v2）をリリースしました。テキストメッセージ（v2）を用いることで、ユーザーへのメンションを指定できます。また、従来より提供しているテキストメッセージに比べて、LINE絵文字をより指定しやすくなりました。

ということで現状通常のメッセージと何が違うのか

大きな感じでまとめると、 **テキストメッセージの中で変数展開ができるようになった** というイメージだと思います。

例えば、ドキュメントにある`Welcome, {user1}! {laugh}\n{everyone} There is a newcomer!`というメッセージを送ると、 `Welcome, @のびすけ! 🐤  @All There is a newcomer!`みたいな感じでメンションや絵文字が展開されるようになります。

変数展開によって今後色々なことがやれるようになるのかもしれませんが、現状は以下の2点がやれることみたいです。

- Botからユーザーにメンションができる
- 絵文字の指定が便利になった

### かなり部分的なバージョンアップ

Messaging APIのバージョンでなく、テキストメッセージの部分だけの更新みたいです。

- v1

```json
{
  "type": "text",
  "text": "hello"
}
```

- v2

```json
{
  "type": "textV2",
  "text": "hello"
}
```

typeの指定が変わります。
従来のtextもそのまま利用は可能でおそらくしばらくは併用な感じな気がします。

### ざっくりとした使い方

> テキストメッセージv2のドキュメント
> https://developers.line.biz/ja/reference/messaging-api/#text-message-v2

```json
{
  "type": "textV2",
  "text": "Welcome, {user1}! {laugh}\n{everyone} There is a newcomer!",
  "substitution": {
    "user1": {
      "type": "mention",
      "mentionee": {
        "type": "user",
        "userId": "U49585cd0d5..."
      }
    },
    "laugh": {
      "type": "emoji",
      "productId": "5a8555cfe6256cc92ea23c2a",
      "emojiId": "002"
    },
    "everyone": {
      "type": "mention",
      "mentionee": {
        "type": "all"
      }
    }
  }
}
```

という感じでv2だと`"type":"textV2"`にしますが、それ以外にも`{user}`などの変数展開をする際に`substitution`を指定する必要があります。

## 試してみる

サクッと試したいですが、 **現状テキストメッセージv2はグループでしか利用できない模様**なので、機能を試すにあたりグループIDが必要になります。

### グループIDの取得（分かる人はスキップ）

簡単なBOTを作ってグループにぶち込みます。

```js
const line = require('@line/bot-sdk');
const express = require('express');

const config = {
    channelAccessToken: ``,
    channelSecret: ``
};

const app = express();

app.post('/webhook', line.middleware(config), (req, res) => {
    Promise
        .all(req.body.events.map(handleEvent))
        .then((result) => res.json(result))
        .catch((err) => {
            console.error(err);
            res.status(500).end();
        });
});

function handleEvent(event) {
    if (event.type !== 'message' || event.message.type !== 'text') {
        return Promise.resolve(null);
    }
    console.log(event);
    const echo = { type: 'text', text: event.message.text };

    return client.replyMessage(event.replyToken, echo);
}

const client = new line.Client(config);

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});
```

### グループIDの取得

適当にグループを作ってBOTを招待してメッセージを投げます。

> ![スクリーンショット 2024-12-20 17.05.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/7f3861a3-9139-140b-b18c-48a9879365ee.png)

`Cxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`みたいなIDが取得できます。

> ![スクリーンショット 2024-12-20 23.52.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/7ac3bee5-c4f9-97eb-83d5-a594d08409fc.png)


## テキストメッセージv2でメンションや絵文字を送信

グループIDを取得できたらプッシュメッセージを送るコードを作って試してみます。
ちなみにGitHub Copilotに書いてもらったコードです。

### 全員にメンションと絵文字

全員にメンションするときは`"type": "all"`を指定します。

```js
const line = require('@line/bot-sdk');

// LINE Botの設定
const config = {
    channelAccessToken: '',
    channelSecret: ''
};

// LINE Clientの作成
const client = new line.Client(config);

// Pushメッセージの送信
const userId = 'Cxxxxxxxxxxxxxxxx'; グループID
const message = {
    type: 'textV2',
    text: 'Welcome! {laugh}\n{everyone} There is a newcomer!',
    substitution: {
        "laugh": {
            "type": "emoji",
            "productId": "670e0cce840a8236ddd4ee4c",
            "emojiId": "002"
        },
        "everyone": {
            "type": "mention",
            "mentionee": {
                "type": "all"
            }
        }
    }
};

client.pushMessage(userId, message)
    .then(() => {
        console.log('Message sent successfully');
    })
  .catch((err) => {
        console.error('Error sending message:', err.originalError.response.data);
    });
```

これで実行すると以下のようなメッセージが送信されます。

> ![スクリーンショット 2024-12-20 23.30.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/4dee24ac-24aa-de6c-35fe-fd9b860213f5.png)

絵文字に関してはドキュメントをみつつproductIdとemojiIdを指定します。

https://developers.line.biz/ja/docs/messaging-api/emoji-list/#line-emoji-definitions

### 個別ユーザーにメンション

`"type": "user"`を指定してユーザーのIDを指定すると個別ユーザーにメンションできます。
個別といってますが、あくまでもグループメッセージ内で送信しないといけないです。

個別メッセージだとメンションする必要はないですからね。

```js
//省略
const userId = 'Cxxxxxxxxxxxxx'; //グループIDを指定
const message = {
    type: 'textV2',
    text: 'Welcome, {user1}! {laugh}\n{everyone} There is a newcomer!',
    substitution: {
        "user1": {
            "type": "mention",
            "mentionee": {
                "type": "user",
                "userId": "Uxxxxxxxxxxxxxxxxxxxxxxxx"
            }
        },
        "laugh": {
            "type": "emoji",
            "productId": "670e0cce840a8236ddd4ee4c",
            "emojiId": "002"
        },
        "everyone": {
            "type": "mention",
            "mentionee": {
                "type": "all"
            }
        }
    }
};

//省略
```

こんな感じで送れます。

> ![スクリーンショット 2024-12-20 23.36.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/a0845ecf-f35c-3a43-48e6-0df6f8cd4e33.png)


## テキストメッセージv2が使えないパターン

試していてエラーが発生したりと動かないケースもありました。

`メンションに関する注意点`ということで、以下の内容に注意らしいです。

> テキストメッセージ（v2）でメンションを指定する際は、以下のことに注意してください。
> https://developers.line.biz/ja/news/2024/10/30/text-message-v2/

- メンションオブジェクトは、応答メッセージまたはプッシュメッセージでのみ使用できます。
- メッセージの送信先は、グループトークまたは複数人トークである必要があります。
- メッセージを送信するLINE公式アカウントは、送信先であるグループトークまたは複数人トークのメンバーである必要があります。
- メンションされたすべてのユーザーは、そのメッセージの送信先であるグループトークまたは複数人トークのメンバーである必要があります。

### 個別LINEに送ってみる

toにグループIDではなく個別のユーザーIDを指定すると

`Mentions are only supported when the destination is a group or room.`というエラーになりました。

![スクリーンショット 2024-12-20 17.53.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/079eb85f-2fbf-031e-b897-d88c6369c2be.png)

### textV2を指定しているがsubstitutionがない状態

以下のコードのようにtextV2を指定しつつ、`{user}`などの変数展開をしようとした書き方をしているのに`substitution`がないとエラーになります。

```js
//省略

const userId = 'Cxxxxxxxxxxxxxxxxxxxxxx'; //グループID
const message = {
    type: 'textV2',
    text: 'Welcome, {user1}! {laugh}\n{everyone} There is a newcomer!'
}

//省略
```

`"The key 'user1' is not found in the substitution map. Please ensure that all keys are defined."`

> ![スクリーンショット 2024-12-20 17.57.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/d0fade39-ecae-f32b-743e-f559e45478eb.png)

### textV2を指定しているけど`{}`がある場合

この辺も気になりますよね

#### `{`だけある

```js
const message = {
    type: 'textV2',
    text: 'Hello~~~{~',
}
```

> ![スクリーンショット 2024-12-20 22.55.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/7f94442c-709e-c998-aa64-c6f683c6aa7b.png)


`Single '{' encountered at index 8. Please use '{{' to escape '{'.`

というエラーに

#### `{}`がある

```js
const message = {
    type: 'textV2',
    text: 'Hello~~~{}~',
}
```

この場合はこんな感じ

> ![スクリーンショット 2024-12-20 22.57.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/fb008d1d-2324-a2ec-0ea9-5a4fdb413c6d.png)


`The key '' enclosed in '{}' does not match the pattern '^[a-zA-Z0-9_]{1,20}$'.`

これもエラーです。

## 逆に`{}`が無ければtextV2で普通のテキストメッセージが可能っぽい

実験的に、 **`{}`をはずしたら`textV2`指定でも普通にテキストメッセージが送られました。**

**...そうなのか。**

```js
const message = {
    type: 'textV2',
    text: 'Hello~~~~',
}
```

> ![スクリーンショット 2024-12-20 22.58.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/fc4c7619-8c7b-e2ae-fa77-1b154abebb55.png)

この場合は普通にテキストメッセージとして送信できる模様です。

## 各種ライブラリは対応した方が良いかも？

実験の通り、普通のテキストメッセージはtextV2指定でも送信できます。

試したところグループでも個別メッセージでもどちらでも問題なかったのでただのテキストを送る際はtextV2に対応しておいてよいかもしれません。`{}`が来た時は注意ですが。

### 重要かも: 今後は新しい機能をテキストメッセージv2のみ追加の可能性

これしれっとすごいこと言ってますよね。しれっと。

> ![スクリーンショット 2024-12-20 23.02.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/65a98157-78a8-0350-4e04-01843917af2a.png)

こうなるとライブラリとか作ってる人はv2にしておいた方が今後良いかもという匂いがします。

ちなみにみそさんが最近作っていたLINE Notify代替のPushメッセージライブラリはtextにしか対応してなさそうでした。対応してほしいですね。

https://qiita.com/miso_develop/items/b13bd0bbf8fc04912f64 

https://github.com/miso-develop/linebot-notify/blob/main/src/modules/api/LinePushApi.ts#L49

![スクリーンショット 2024-12-20 17.22.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/ee9f700b-f9eb-21ad-93f0-a5ed7b090bba.png)

## まとめ

まだそこまで注目されてる感じがしませんが、テキストメッセージv2が今後主流になる可能性がある気配です。

グループでのユーザーへのメンションができるのは結構便利機能なので利用したい方には待望機能なのかも。

`こんにちは {image}`みたいな画像の変数展開などはApple Intelligenceなどで絵文字の生成がやれるようになったりしてそういうニーズが増えるかもなどは思ったのでその辺先駆け意識とかあるかもしれませんね。

https://news.mynavi.jp/article/20241125-3071413/

ライブラリ作ってる人は少し意識しておくと良いかと思います。

自分にもブーメラン