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

はじめに

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

このページでは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

 

5. 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

OAuth Permission scopes

https://api.slack.com


 

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)で実装する方はこちらをご参考ください。

 

GitHub – seratch/deepl-for-slack: Slack app for DeepL Translate API us…

https://github.com


 

GitHub – slack-samples/deno-message-translator: Translate message text…

https://github.com


 

GitHub – slackapi/reacjilator: A translation bot that translates a mes…

https://github.com


 

 

まとめ

一通り実装してみた感想はDeepL API周りは割と分かりやすくて、特に問題なかったんですが、
Slackの設定とAWS実装で色々試行錯誤しました。
 
今回の実装の開発環境で必須になるSlackDeepLとは違って
AWS環境は自作サーバーでも他のサーバーレスクラウドでも何でも使いやすい環境で各自試してみてください。

 


 

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

 

DeepL を Slack から使おう! – Qiita

https://qiita.com


 

 


 

ココネでは一緒に働く仲間を募集中です。

ご興味のある方は、ぜひこちらの採用特設サイトをご覧ください。

https://www.cocone.co.jp/recruit/contents/

 

Category

Tag