Discord のメンションを LINE に通知する Bot

## はじめに
Discord の自分宛てのメンションを LINE に通知してくれる Bot を作成しました。LINE の通知をスマートウォッチに通知させ、Disocrd のメンションに気づくという流れになります。作成した経緯としては以下になります。
1. PC を立ち上げてないときでも Discord にメンションされたら気づきたい
2. Discord の通知を全てスマートウォッチに通知させるのはうるさい（メンションのみを通知させることも可能だが、通常のメッセージの通知が来なくなるので実用的でない）
3. ほとんど通知が来ない LINE へメンションされたことを通知すればいいのでは（連絡のやり取りは基本 Discord で LINE はメインで使用しない前提）
4. LINE の通知をスマートウォッチに通知させる

以下、ソースコードになります。

https://github.com/Pumi1a/chkmention

## 環境
* Raspberry Pi 4 Model B
    * CentOS Stream 8
        * Python 3.11.0
            * discord.py 2.1.0
* LINE Notify

Raspberry Pi に CentOS Stream 8 を入れて Bot を動かしています。自前サーバを持っていない方は、無料のホスティングサービスを選択するのがいいでしょう。Raspberry Pi のセットアップ方法と、ホスティングサービスの使い方を記事にまとめたので参考にしてみて下さい。

https://qiita.com/Pumila/items/4f73263025ffbc427e90

https://qiita.com/Pumila/items/29f26fb349d5592046ae

## 導入

### Bot アカウントの作成
<a href="https://discord.com/developers">Discord Developer Portal</a> より Bot アカウントを作成しましょう。詳細な手順については既にまとまっている記事があるため省きます。以下の記事を参考にして下さい。
実装においてアクセストークンが必要になります。メモしておきましょう。

https://qiita.com/1ntegrale9/items/cb285053f2fa5d0cccdf


### Bot アカウントの設定
メッセージ取得のために Bot の追加設定が必要になります。<font color="red"> この設定を行わないとメッセージが取得できません。</font><a href="https://discord.com/developers">Discord Developer Portal</a> から対象の [App] を選択し、[Bot] の項目の `Privileged Gateway Intents` より `MESSAGE CONTENT INTENT` を有効化します。設定を保存するのを忘れないようにしましょう。
<img width="600" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115291/77c9d2c6-1651-0f2a-7c09-fe47a454af5f.png">


### LINE Notify のアクセストークン発行
<a href="https://notify-bot.line.me/ja/">ここ</a>からログインし、マイページからアクセストークンを発行します。ログインするには LINE アカウントにメールアドレスを紐づけている必要があります。手順は以下のとおりです。
1. LINE アプリを開き、[ホーム]＞[設定]＞[アカウント]＞[メールアドレス] をタップ
2. メールアドレスを入力し [次へ] をタップ
3. 届いた認証番号を入力、または URL＞[OK] をタップ

ログインできたら、以下の手順でアクセストークンを発行します。
1. 右上から [マイページ] を開く
2. [トークンを発行する] をクリック
3. トークン名を記入し、通知を送信するトークルームを選択する（私は自分しか入っていないグループを作り、そこに送信しています。[1:1でLINE Notifyから通知を受け取る] を選択しても構いません）
4. [発行する] をクリック
　　　　<img width="300" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115291/ce839da8-f15a-289b-575f-bda348e62f72.png">




5. 発行したトークンが表示されます。<font color="red">トークンの再発行はできません。必ずメモしておきましょう。</font>（まあ、忘れたら連携解除してトークンを再度発行すればいいだけですが…）

### コードの作成と実行
ここからは Python のソースコードになります。まずは <a href="https://github.com/Rapptz/discord.py"> discord.py</a> と requests モジュールをインストールします。
```console:モジュールのインストール
$ python3 -m pip install -U discord.py requests
```
以下のコードを `chkmention.py` ファイルとして保存します。
```python:chkmention.py
#!/usr/bin/env python3
import discord
import requests 

# 作成した Bot のアクセストークンに置き換えて下さい
DISCORD_TOKEN = 'YourDiscordAccsessToken'
# クライアント接続
intents = discord.Intents.none()
intents.messages = True
# discord.py Ver2.0 以前ではコメントアウトして下さい
intents.message_content = True
client = discord.Client(intents=intents)

# 起動時の処理（無くても問題ない）
@client.event
async def on_ready():
    print('ログインしました')

# Bot が所属しているチャンネルにメッセージがされた時に動作する処理
@client.event
async def on_message(message):
# Bot からのメッセージは無視
    if message.author.bot:
        return
# @everyone の場合、LINE に通知する
    if message.mention_everyone:
# メッセージの投稿主
        author = message.author
# メッセージの内容
        msg = message.content
# メッセージ内容の整形
        msg = msg.replace('@everyone','')
        msg = f'From:{author}\nMessage:{msg}'
        send_notify(msg)
        return
# メンションじゃない場合は無視
    if not message.mentions:
        return
# メンションされたユーザ名を取得
    for mention in message.mentions:
        name = mention.name
# メンションされたユーザ名が自分だったら LINE に通知する
# Discord のユーザ名に置き換えて下さい。Discord 左下の"#数字列"の前部分
    if name == 'YourName':
        author = message.author
        msg = message.content
# メッセージ内容の整形。自分のユーザ ID に置き換えて下さい
        msg = msg.replace('<@YourID>','')
        msg = f'From:{author}\nMessage:{msg}'
        send_notify(msg)

# LINE にメッセージを送る処理
def send_notify(message):
# LINE Notify のアクセストークンに置き換えて下さい
    LINE_TOKEN = 'YourLINEAccsessToken'
    api_url = 'https://notify-api.line.me/api/notify'
    headers = {'Authorization': f'Bearer {LINE_TOKEN}'}
    data = {'message': f'{message}'}
    requests.post(api_url,headers=headers,data=data)

client.run(DISCORD_TOKEN)
```
クライアント接続における Intents は必要最低限にしています。Intents については記事にまとめたので参考にしてみて下さい。

https://qiita.com/Pumila/items/8b8e14f60fd7f266872b

コード中の Discord のユーザ名とは、Discord 左下の"#数字列"前が該当します。以下の赤線で伏せてある部分になります。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115291/4aa40619-317c-4d64-3132-6d47318a10ba.png)

**2023/10/08追記**
Discordの仕様が変更されたため、ユーザ名を変更できるようになりました。ユーザ名は以下画像の赤枠で囲った部分になります。大文字小文字が区別されるため注意して下さい。
![screenshot2023-10-08 20.09.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115291/e2677d7b-f978-8261-6cc2-501828af41d8.png)


またユーザ ID は Discord の詳細設定より`開発者モード`を有効化し、自分のアイコンを右クリックすることで取得できます。

以上のコードを実行すると以下のように LINE に通知されます。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115291/b319ba81-7337-4108-c881-20ffe41616b7.png)

## service への登録
この Bot を常時稼働させておくために、サービスとして登録しておきましょう（Linux サーバを用いて Bot を運用する場合）。登録するためには root 権限が必要になります。まずは、以下ディレクトリに移動してください。
```console
[root@localhost ~]# cd /etc/systemd/system/
```
その後、以下のコードを `chkmention.service` として保存して下さい。
```bash:chkmention.service
[Unit]
Description=chkmention

[Install]
WantedBy=multi-user.target

[Service]
# 実行したいユーザに置き換えて下さい
User=web
# 実行するコードのディレクトリに置き換えて下さい
ExecStart=/home/web/discord/line/chkmention.py
Restart=always
```
最後にサーバ起動時にサービスも自動起動してくれるように設定します。
```console:サービスの自動起動
[root@localhost system]# systemctl start chkmention.service
[root@localhost system]# systemctl enable chkmention.service
Created symlink /etc/systemd/system/multi-user.target.wants/chkmention.service → /etc/systemd/system/chkmention.service.
```
以下コマンドを実行して `Active: active (running)` と表示されていれば問題ありません。
```console:サービスの状態
[root@localhost system]# systemctl status chkmention.service 
● chkmention.service - chkmention
   Loaded: loaded (/etc/systemd/system/chkmention.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2023-02-04 21:15:38 JST; 973ms ago
 Main PID: 4590 (python3)
    Tasks: 2 (limit: 23888)
   CGroup: /system.slice/chkmention.service
           └─4590 python3 /home/web/discord/chkmention.py

Feb 04 21:15:38 localhost.localdomain systemd[1]: Started chkmention.
```

## 最後に
PC スリープ時に Discord にメンションされても、気づけるようになりました。

## 参考
<a href="https://qiita.com/akeome/items/e1e0fecf2e754436afc8"> PythonでLINE Notifyへ通知を送る - Qiita</a>