LoginSignup
1
0

More than 1 year has passed since last update.

DeepL API ProをSlackのアプリとして連動する

Last updated at Posted at 2023-03-13

はじめに

ココネ株式会社のサービス基盤開発室クライアントチームでツール開発している鞠(クク)です。

このページではDeepLでSlack用の翻訳ツールを作成してみました。

仕様

本ツールは、Slack上の文言に対してDeepLを利用して自動翻訳してくれるツールになります。
やり方はSlackのメッセージに対して、国旗のリアクションを行うと、自動翻訳されたメッセージがスレッドに投稿されます。

deepl_sample3.png

DeepLとは?

DeepL翻訳は、
2017年8月28日にサービスを開始したニューラル機械翻訳サービス。
ドイツのケルンに本拠地を置く DeepL GmbH が開発。

Google 翻訳よりも精度が高く、微妙なニュアンスのある翻訳ができると肯定的な報道と評価を受けている。

2023年1月31日に韓国語とノルウェー語がリリースされました。

開発環境

  • DeepL API Pro(for Developers)
  • Slack ワークスペース
  • AWS API Gateway
  • AWS Lambda

DeepL API Pro

無料版でも利用可能ですが、有料版のメリットとしては、
機密性が高い社内の情報を一瞬でもDeepLのサーバー側に保存されない上、
機械学習にも使われないようになります。

1. 契約プラン

月使用量と、1,000,000文字あたり¥2,500

登録料金 ¥630 /月 + 従量課金制 100万文字あたり¥630

image.png

2. DeepL API関連技術ドキュメント

3. DeepL APIで使用する認証キー

正常に登録を完了すると、次のアカウント情報ページに認証キーとAPIのドメインが表示されます。
LambdaでAPIコールするとき、必要になります。

4. 使用量確認(文字数&料金)

次のURLで文字数&料金が確認できます。

AWS API Gateway

1. 概要

image.png

2. REST APIを作成

3. POSTメソッドを作成

Resourcesの [Actions]->[Create Method]->[POST] メソッドを作成します。

4. Method Execution / - POST - Integration Request設定

Integration typeでLambda関数を選びます。
Use Lambda Proxy integrationをチェックします。

スクリーンショット 2023-03-07 21.46.29.png

4. REST API のステージのセットアップ

[Actions]->[Deploy API]でDeployment stageで[New Stage]を指定して入力後デプロイします。
Stage名は自由に入力してください。

スクリーンショット 2023-03-07 21.55.10.png

6. REST API のデプロイ

デプロイ後、生成されたURLを下記のSlack APIのアプリに入力します。
(Slack API -> 登録アプリ -> Event Subscriptions -> Request URL)

AWS Lambda

こちらのコードはPython 3.9 Runtimeで動作確認しました。


import json
import os
import requests


CURRENT_PROJECT_VERSION = "0.0.1"
SLACK_CONVERSATIONS_REPLIES_URL = "https://slack.com/api/conversations.replies" 
SLACK_CHAT_POST_MESSAGE_URL = "https://slack.com/api/chat.postMessage" 

SLACK_TOKEN = os.environ.get('SLACK_TOKEN')
DEEPL_KEY = os.environ.get('DEEPL_KEY')
DEEPL_URL = os.environ.get('DEEPL_URL')
DEBUG_MODE = os.environ.get('DEBUG_MODE')

#data mapping between reaction names and language codes
LANG_CODES = {
  'us': 'en-us', #英語アメリカ
  'gb': 'en-gb', #英語イギリス
  'cn': 'ZH', #中国語
  'de': 'de', #ドイツ語
  'fr': 'fr', #フランス語
  'it': 'it', #イタリア語
  'jp': 'ja', #日本語
  'es': 'es',#スペイン語
  'nl': 'nl', #オランダ語
  'pl': 'pl', #ポーランド語
  'ru': 'ru', #ロシア語
  'flag-ua': 'uk', #Ukrainian
  'kr': 'ko', #韓国語
};
                
def is_challenge(event):
    if 'body' in event:
        body = json.loads(event['body'])
        if ('type' in body) & (body['type'] == 'url_verification'):
            return body['challenge']

def process_message(event):
    if 'body' in event:
        body = json.loads(event['body'])
        event_body = body['event']
        if ('type' in event_body) & (event_body['type'] == 'reaction_added') & ('reaction' in event_body) & (event_body['reaction'] in LANG_CODES):
            event_reaction = event_body['reaction']
            event_item = event_body['item']
            event_channel = event_item['channel']
            event_ts = event_item['ts']
            
            header_message={
                "Authorization": "Bearer {}".format(SLACK_TOKEN)
            }
            
            payload  = {
                "channel" : event_channel,
                "ts" : event_ts
            }
            res = requests.get(SLACK_CONVERSATIONS_REPLIES_URL, headers=header_message, params=payload)
            
            t_data = res.json()
            original_message = t_data['messages'][0]['text']
            
            if(DEBUG_MODE):
                print("original_message : ", original_message)
                
            trans_lang = LANG_CODES[event_reaction]

            # パラメータの指定
            deepl_params = {
                        "auth_key" : DEEPL_KEY,
                        "text" : original_message,
                        "target_lang": trans_lang  # 翻訳後の言語
                    }
            
            deepl_response = requests.post(DEEPL_URL, data=deepl_params) # URIは有償版, 無償版で異なるため要注意 -> 個人用

            trans_data = deepl_response.json()
            translate_messages = trans_data['translations'][0]['text']

            if(DEBUG_MODE):
                print("translate_messages : ", translate_messages)
                
            #判別ロージック追加
            marge_translate_messages = ":"+event_body['reaction']+": "+trans_lang+"\n"+translate_messages
                
            for i in t_data['messages']:
                if ('bot_id' in i) & (i['text'] == marge_translate_messages):
                    return

            chatpayload  = {
                "channel" : event_channel,
                "text" : marge_translate_messages,
                "thread_ts" : event_ts
            }
            
            if(DEBUG_MODE):
                print("marge_translate_messages : ", marge_translate_messages)
            
            res_chat = requests.post(SLACK_CHAT_POST_MESSAGE_URL, headers=header_message, params=chatpayload)
            return res.json()
    return

def lambda_handler(event, context):
    # Return Slack challenge parameter
    clg = is_challenge(event = event)
    
    process_message(event = event)

    return {
        "statusCode": 200,
        "headers": {
            "Content-Type": "application/json"
        },
        "body": json.dumps({
            "challenge ": clg
        })
    }

※コメントなどのリアクションがあったら、現ソースコードをリファクタリングする予定です。

Slack アプリケーション登録

1. アプリを登録

Slackにログインした状態で、上記のURLにアクセスします。
[Create an App]をクリックしてアプリの名前と
下記の文言の後にアプリを使用するWorkspaceを選択します。
Pick a workspace to develop your app in:

2. アプリの権限を設定

左上のメニューから Features -> OAuth & Permissions を選択

スクリーンショット 2023-03-10 14.20.42.png

上記の画面の Scopes -> Bot Token Scopesの[Add an OAuth Scope]で権限をを追加します。

権限 詳細
channels:history メッセージの参照、履歴の参照
groups:history プライベート チャンネルのメッセージの参照、履歴の参照
chat:write チャンネルに投稿
reactions:read メッセージにつけられたリアクションを参照

3. ボットの設定

こちらではボットの名とメンション名の設定します。
左のメニューから Features -> App Home 選択
App Display Name -> Edit ボタンを押して、設定を行います。

スクリーンショット 2023-03-10 14.57.42.png
スクリーンショット 2023-03-10 14.58.05.png

4. アプリの外見設定

左のメニューから Settings -> Basic Information -> Display Information
アプリの設定画面で、アプリ名、説明文、バックグラウンドカラー、アイコン画像など設定します。

スクリーンショット 2023-03-10 15.12.21.png

5. アプリをワークスペースにインストール

左のメニューから Settings -> Install App を選択します。
(Features -> OAuth & Permissionsからも同様の操作が可能です。)

スクリーンショット 2023-03-10 15.29.21.png

権限によって実装内容が次のように変わります。
A. 管理者権限がある場合
 [Install App to Workspace] でインストール後そのまま許可できます。
B. 一般権限の場合
 [Request to Install] でインストールを依頼して管理者の承認待ちになります。

Slack Enterprise Grid Planの場合
複数のワークスペースで共通して使える Org-Wide Appをインストールできます。

5. アプリのトークンを取得

インストール後には 左のメニューの
Settings -> Install App 又は Features -> OAuth & Permissions
xoxb- から始まる Bot User OAuth Access Token が取得できます。

また、セキュリティなどの必要に応じていつでもトークンが再発行できます。
Features -> OAuth & Permissions -> Revoke All OAuth Tokens -> [Revoke Tokens]

6. Event Subscriptions設定

翻訳するときリアクションが付けることになりますが、
その時の確認のためイベントのサブスクライブ機能を使用します。

左のメニューの Features -> Event Subscriptions -> Enable Events -> [Off] クリックします。

スクリーンショット 2023-03-10 16.23.14.png

Request URLにAWS HTTP GatewayからデプロイしたURLを記入します。

スクリーンショット 2023-03-10 16.23.38.png

最初にURLを登録するにはchallenge認証が必要です。

Lambdaの次の関数で実装されています。

def is_challenge(event):

設定内容としては以下のように機能を有効にして Request URL を設定し、bot events の方に reaction_added を追加し [Save Changes] ボタンを押して保存するだけです。

スクリーンショット 2023-03-10 16.38.00.png

Basic Information -> Building Apps for Slack -> Add features and functionality
設定画面は最終的に次のようになります。

スクリーンショット 2023-03-08 16.49.09.png

7. アプリをチャンネルに招待して動作確認

対象Slack チャンネルアプリのボットユーザーを招待します。
チャンネル詳細 -> インテグレーション -> App -> [アプリを追加する]
アプリを検索して [追加]

スクリーンショット 2023-03-10 16.41.06.png

メッセージに翻訳したい国の国旗の絵文字をリアクションでつけてください。
:flag-fr:

スクリーンショット 2023-03-10 16.17.45.png

参照コード一覧 

Python以外の言語(JS, TS) で実装する方はこちらをご参考ください。

まとめ

一通り実装してみた感想はDeepL API周りは割と分かりやすくて、特に問題なかったんですが、
Slackの設定とAWS実装で色々試行錯誤しました。

今回の実装の開発環境で必須になるSlackDeepLとは違って
AWS環境は自作サーバーでも他のサーバーレスクラウドでも何でも使いやすい環境で各自試してみてください。


サーバー周りの環境をHerokuでご利用の方は次のKazuhiro Sera様の次のドキュメントをご参考ください。

1
0
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
1
0