0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Open AI にSlack→Teames作らせてみた

Posted at

やり取りのトランスクリプト

ユーザー

Slackのトーク履歴をTeamesにInport出来るようなツールを開発したいが可能か?

アシスタント

技術的には可能ですが、いくつかの注意点と課題があります。

主な検討事項

  1. APIの利用と制限

    • Slack側: Slackはワークスペースのトーク履歴をエクスポートするためのAPI(またはエクスポート機能)を提供している。ただし、取得できるデータはプランやワークスペースの設定に依存する。
    • Microsoft Teams側: Teamsは Microsoft Graph API を通じてチャネルやメッセージの操作が可能ですが、「インポート」という直接的な API は存在しない。そのため、Slackのメッセージを再投稿する必要があるかもしれません。
  2. データの変換と整合性

    • SlackとTeamsではメッセージのフォーマットやメタ情報(投稿者、タイムスタンプ、添付ファイルなど)が異なるため、フォーマット変換のロジックが必要です。
  3. 自動化ツールの開発

    • スクリプトやミドルウェアを作成して、SlackのエクスポートデータをTeams形式に変換し、Microsoft Graph API やWebhookを利用して再投稿する仕組みが考えられます。
  4. ユーザー体験と移行の影響

    • 移行期間中の一貫性やユーザーへの通知など、移行時のユーザー体験も検討する必要があります。

まとめ

Slackのトーク履歴をTeamsに「インポート」するツールは、以下の流れで開発可能です。

  1. Slackのトーク履歴をエクスポート・取得する
  2. エクスポートデータをTeams用の形式に変換する
  3. Teamsに新規投稿として登録する

なお、各システムのAPI仕様や認証・セキュリティ面の検証・テストは十分に行ってください。


ユーザー

Pythonでのrequestsライブラリを利用した実装例を作成して

アシスタント

以下は、Python の requests ライブラリを利用して、Slackのトーク履歴を取得し、TeamsのWebhookを使ってTeamsに投稿する基本的な実装例です。

import requests
import json

# -------------------------------
# 設定(それぞれご自身の情報に置き換えてください)
# -------------------------------

# Slack APIトークン(Bot Token or User Token)とチャンネルID
SLACK_API_TOKEN = 'xoxp-your-slack-token'
SLACK_CHANNEL_ID = 'C01234567'  # 例: "C01234567"

# Microsoft TeamsのIncoming Webhook URL
TEAMS_WEBHOOK_URL = 'https://outlook.office.com/webhook/your-teams-webhook-url'

# Slackの会話履歴を取得するAPIエンドポイント
SLACK_CONVERSATION_HISTORY_URL = 'https://slack.com/api/conversations.history'


# -------------------------------
# Slackからメッセージを取得する関数
# -------------------------------
def get_slack_messages():
    params = {
        'channel': SLACK_CHANNEL_ID,
        'limit': 100  # 必要に応じて件数を調整
    }
    headers = {
        'Authorization': f'Bearer {SLACK_API_TOKEN}'
    }

    response = requests.get(SLACK_CONVERSATION_HISTORY_URL, params=params, headers=headers)
    if response.status_code != 200:
        raise Exception(f"Slackからの取得に失敗しました: {response.status_code} {response.text}")

    data = response.json()
    if not data.get('ok'):
        raise Exception(f"Slack APIエラー: {data.get('error')}")
    return data.get('messages', [])


# -------------------------------
# Teamsへメッセージを投稿する関数
# -------------------------------
def post_to_teams(message_text):
    # シンプルなメッセージをTeamsへ送信するためのペイロード
    payload = {
        "text": message_text
    }
    response = requests.post(TEAMS_WEBHOOK_URL, json=payload)
    if response.status_code not in [200, 201]:
        raise Exception(f"Teamsへの投稿に失敗しました: {response.status_code} {response.text}")
    return response.text


# -------------------------------
# メイン処理
# -------------------------------
def main():
    try:
        messages = get_slack_messages()
    except Exception as e:
        print(f"Slackからメッセージを取得できませんでした: {e}")
        return

    # Slackでは新しいメッセージがリストの先頭の場合が多いため、順番を逆にして古い順に投稿する場合
    for message in reversed(messages):
        user = message.get('user', 'unknown')
        text = message.get('text', '')
        timestamp = message.get('ts', 'unknown')

        # シンプルなフォーマットでTeamsに投稿するメッセージを作成
        team_message = f"**User:** {user}\n**Time:** {timestamp}\n**Message:**\n{text}"

        print("Teamsへ以下のメッセージを投稿します:")
        print(team_message)
        try:
            result = post_to_teams(team_message)
            print("投稿成功:", result)
        except Exception as e:
            print("Teamsへの投稿に失敗しました:", e)


if __name__ == '__main__':
    main()

※ 本サンプルは基本例ですので、実環境で使用する際には認証情報の管理やエラーハンドリングの強化等、必要に応じて拡張してください。


ユーザー

SlackでExportしたJsonをTeamesのフォーマットに変換して

アシスタント

以下は、Slackでエクスポートした JSON(例として、各チャネルごとの JSON ファイルにメッセージが格納されている形式)を読み込み、TeamsのIncoming Webhookで投稿できるような Markdown 形式に変換するサンプルコード例です。

import json
import os
import requests

# ---------------------------------------------------
# 設定:各自の環境に合わせたSlackエクスポートファイルパスやTeams Webhook URLを設定
# ---------------------------------------------------

# Slackエクスポートで出力されたファイル
SLACK_CHANNEL_EXPORT_FILE = "general.json"  # 例:#general チャンネルのメッセージが格納されたJSONファイル
SLACK_USERS_FILE = "users.json"             # オプション:ユーザー情報が格納されたJSONファイル

# Microsoft TeamsのIncoming Webhook URL
TEAMS_WEBHOOK_URL = "https://outlook.office.com/webhook/your-teams-webhook-url"

# ---------------------------------------------------
# Slackエクスポートデータの読み込み
# ---------------------------------------------------

def load_json_file(file_path):
    """JSONファイルを読み込む"""
    with open(file_path, "r", encoding="utf-8") as f:
        return json.load(f)

# ---------------------------------------------------
# ユーザーID --> ユーザー名のルックアップテーブル作成(users.jsonから)
# ---------------------------------------------------

def build_users_lookup(users_file_path):
    if not os.path.exists(users_file_path):
        return {}
    users = load_json_file(users_file_path)
    lookup = {}
    for user in users:
        lookup[user.get("id")] = user.get("name") or user.get("real_name") or "unknown"
    return lookup

# ---------------------------------------------------
# SlackメッセージをTeamsフォーマットに変換する関数
# ---------------------------------------------------

def convert_slack_message_to_teams_format(message, users_lookup=None):
    """
    Slackからの1件のメッセージをTeamsに投稿する形式(Markdown)に変換する関数。
    """
    user_id = message.get("user", "unknown")
    # ユーザー名ルックアップがあれば展開
    username = users_lookup.get(user_id, user_id) if users_lookup else user_id
    text = message.get("text", "")
    timestamp = message.get("ts", "unknown")

    teams_message = (
        f"**User:** {username}\n"
        f"**Time:** {timestamp}\n"
        f"**Message:**\n{text}"
    )
    return teams_message

# ---------------------------------------------------
# 変換処理:Slackエクスポートファイルの全メッセージをTeams形式に変換
# ---------------------------------------------------

def convert_slack_export_to_teams_messages(channel_file, users_lookup=None):
    """
    Slackのチャネルエクスポートファイルのメッセージを読み込み、
    Teamsに投稿可能な形式のメッセージリストを返す。
    """
    messages = load_json_file(channel_file)
    teams_messages = []
    for msg in messages:
        teams_msg = convert_slack_message_to_teams_format(msg, users_lookup)
        teams_messages.append(teams_msg)
    return teams_messages

# ---------------------------------------------------
# Teamsへの投稿(Webhookを利用)
# ---------------------------------------------------

def post_to_teams(message_text):
    """
    TeamsのIncoming Webhookに対してメッセージを送信する関数
    """
    payload = {
        "text": message_text  # TeamsではMarkdown記法が利用可能です
    }
    response = requests.post(TEAMS_WEBHOOK_URL, json=payload)
    if response.status_code not in [200, 201]:
        raise Exception(f"Teamsへの投稿に失敗しました: {response.status_code} {response.text}")
    return response.text

# ---------------------------------------------------
# メイン処理例
# ---------------------------------------------------

def main():
    # ユーザー情報のロード(オプション)
    users_lookup = build_users_lookup(SLACK_USERS_FILE)
    
    # SlackエクスポートされたチャネルファイルからメッセージをTeams形式に変換
    teams_messages = convert_slack_export_to_teams_messages(SLACK_CHANNEL_EXPORT_FILE, users_lookup)
    
    # 各メッセージを確認しながらTeamsに投稿(または単に変換結果を出力)
    for msg in teams_messages:
        print("=" * 40)
        print(msg)
        # 実際にTeamsに投稿する場合は以下の行のコメントを外す
        try:
            result = post_to_teams(msg)
            print("Teamsへの投稿成功:", result)
        except Exception as e:
            print("Teamsへの投稿エラー:", e)

if __name__ == '__main__':
    main()

このサンプルコードをベースに、ご自身の環境や要件に合わせて調整してください。


ユーザー

その二つのサンプルを一つに結合
SlackからExport
Teamesフォーマットに変換
Teamesにinput

アシスタント

以下は、Slack の Export した JSON を読み込み、Teams 用のフォーマットに変換した上で、Teams の Incoming Webhook に投稿する一連の処理を 1 つのスクリプトに統合したサンプルです。

import json
import os
import requests
from datetime import datetime

# ---------------------------------------------------
# 設定:各自の環境に合わせたファイルパスやTeams Webhook URLを設定
# ---------------------------------------------------
# Slack Exportファイル(各チャンネルのJSONファイル)
SLACK_CHANNEL_EXPORT_FILE = "general.json"  # 例:#general チャンネルのメッセージが格納されたJSONファイルのパス
SLACK_USERS_FILE = "users.json"             # オプション:ユーザー情報を管理するJSONファイルのパス

# Microsoft TeamsのIncoming Webhook URL
TEAMS_WEBHOOK_URL = "https://outlook.office.com/webhook/your-teams-webhook-url"

# ---------------------------------------------------
# JSONファイルの読み込み関数
# ---------------------------------------------------
def load_json_file(file_path):
    """指定されたJSONファイルを読み込んで返す"""
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"ファイルが存在しません: {file_path}")
    with open(file_path, "r", encoding="utf-8") as f:
        return json.load(f)

# ---------------------------------------------------
# ユーザーIDからユーザー名へのルックアップテーブル作成関数
# ---------------------------------------------------
def build_users_lookup(users_file_path):
    """users.jsonからユーザーIDと名前の辞書マップを作成する"""
    try:
        users = load_json_file(users_file_path)
    except Exception as e:
        print(f"ユーザー情報ファイルの読み込みに失敗しました: {e}")
        return {}
    lookup = {}
    for user in users:
        lookup[user.get("id")] = user.get("name") or user.get("real_name") or "unknown"
    return lookup

# ---------------------------------------------------
# SlackメッセージをTeams用フォーマット(Markdown)に変換する関数
# ---------------------------------------------------
def convert_slack_message_to_teams_format(message, users_lookup=None):
    """
    Slack Exportからの1件のメッセージをTeamsに投稿可能な形式(Markdown)に変換する
    """
    user_id = message.get("user", "unknown")
    username = users_lookup.get(user_id, user_id) if users_lookup else user_id
    text = message.get("text", "")
    ts = message.get("ts", "")
    # tsは文字列のUnixタイムスタンプなので、日付フォーマットへ変換
    try:
        timestamp = datetime.fromtimestamp(float(ts)).strftime("%Y-%m-%d %H:%M:%S")
    except Exception:
        timestamp = ts

    teams_message = (
        f"**User:** {username}\n"
        f"**Time:** {timestamp}\n\n"
        f"**Message:**\n{text}"
    )
    return teams_message

# ---------------------------------------------------
# Slack Exportファイル内の全メッセージをTeamsフォーマットに変換する関数
# ---------------------------------------------------
def convert_slack_export_to_teams_messages(channel_file, users_lookup=None):
    """
    Slackのチャネルエクスポートファイルからメッセージを読み込み、
    Teamsに投稿可能な形式のメッセージリストを返す
    """
    try:
        messages = load_json_file(channel_file)
    except Exception as e:
        raise Exception(f"Slackエクスポートファイルの読み込みに失敗しました: {e}")

    teams_messages = []
    for msg in messages:
        teams_msg = convert_slack_message_to_teams_format(msg, users_lookup)
        teams_messages.append(teams_msg)
    return teams_messages

# ---------------------------------------------------
# Teamsへの投稿関数(Webhookを利用)
# ---------------------------------------------------
def post_to_teams(message_text):
    """
    TeamsのIncoming Webhookに対してメッセージを送信する
    """
    payload = {
        "text": message_text  # TeamsではMarkdownがサポートされています
    }
    response = requests.post(TEAMS_WEBHOOK_URL, json=payload)
    if response.status_code not in [200, 201]:
        raise Exception(f"Teamsへの投稿に失敗しました: {response.status_code} {response.text}")
    return response.text

# ---------------------------------------------------
# メイン処理
# ---------------------------------------------------
def main():
    # ユーザー情報のルックアップテーブルを構築
    users_lookup = {}
    try:
        users_lookup = build_users_lookup(SLACK_USERS_FILE)
    except Exception as e:
        print(f"ユーザー情報のルックアップ構築に失敗しました: {e}")

    # Slack ExportファイルのメッセージをTeams形式に変換
    try:
        teams_messages = convert_slack_export_to_teams_messages(SLACK_CHANNEL_EXPORT_FILE, users_lookup)
    except Exception as e:
        print(f"Slackメッセージの変換に失敗しました: {e}")
        return

    # 各メッセージをTeamsへ投稿(または確認のためにコンソール出力)
    for msg in teams_messages:
        print("=" * 40)
        print(msg)
        # Teamsへ実際に投稿する場合は下記コメントアウトを外してください
        try:
            result = post_to_teams(msg)
            print("Teamsへの投稿成功:", result)
        except Exception as e:
            print("Teamsへの投稿エラー:", e)

if __name__ == '__main__':
    main()

このサンプルをベースに、環境に合わせた拡張・調整を行ってください。


ユーザー

このスクリプトを毎月1日の12時に動かすと仮定して

1か月分のデータのみの出力で作ってみて
またSlackのチャンネルは複数あると仮定して複数のTeamesのチャンネルにInputして

アシスタント

以下は、毎月1日の12時に実行され、前月分のデータのみを抽出し、複数のSlackチャンネル(各チャンネル毎にエクスポートファイルがある想定)をそれぞれ対応するTeamsチャンネルへ投稿するサンプルコードです。

import json
import os
import requests
from datetime import datetime, timedelta

# ---------------------------------------------------
# 設定: SlackエクスポートファイルとTeams Webhook URLのマッピング
# ---------------------------------------------------
CHANNEL_MAPPING = {
    "general": {
        "export_file": "general.json",  # Slackエクスポートファイルのパス(例:#general)
        "teams_webhook": "https://outlook.office.com/webhook/your-teams-webhook-general"
    },
    "random": {
        "export_file": "random.json",   # Slackエクスポートファイルのパス(例:#random)
        "teams_webhook": "https://outlook.office.com/webhook/your-teams-webhook-random"
    }
}

# ユーザー情報ファイル(オプション)
SLACK_USERS_FILE = "users.json"

# ---------------------------------------------------
# JSONファイル読み込みの共通関数
# ---------------------------------------------------
def load_json_file(file_path):
    """指定されたJSONファイルを読み込んで返す"""
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"ファイルが存在しません: {file_path}")
    with open(file_path, "r", encoding="utf-8") as f:
        return json.load(f)

# ---------------------------------------------------
# ユーザーIDからユーザー名へのルックアップテーブル構築
# ---------------------------------------------------
def build_users_lookup(users_file_path):
    """users.jsonから、ユーザーIDと名前のマッピングを返す"""
    try:
        users = load_json_file(users_file_path)
    except Exception as e:
        print(f"ユーザー情報ファイルの読み込みに失敗しました: {e}")
        return {}
    lookup = {}
    for user in users:
        lookup[user.get("id")] = user.get("name") or user.get("real_name") or "unknown"
    return lookup

# ---------------------------------------------------
# 前月の開始日と終了日を計算する
# ---------------------------------------------------
def get_last_month_range():
    """
    現在日付から前月の開始日と終了日を返す
    例)2025-03-01に実行 → 前月は2025-02-01 00:00:00 ~ 2025-02-28 23:59:59
    """
    now = datetime.today()
    first_of_this_month = datetime(year=now.year, month=now.month, day=1)
    last_month_end = first_of_this_month - timedelta(seconds=1)
    last_month_start = datetime(year=last_month_end.year, month=last_month_end.month, day=1)
    return last_month_start, last_month_end

# ---------------------------------------------------
# SlackメッセージをTeams用Markdownに変換する関数
# ---------------------------------------------------
def convert_slack_message_to_teams_format(message, users_lookup=None):
    """
    Slackの1件のメッセージをTeams向けのMarkdown形式に変換する
    """
    user_id = message.get("user", "unknown")
    username = users_lookup.get(user_id, user_id) if users_lookup else user_id
    text = message.get("text", "")
    ts = message.get("ts", "")
    try:
        timestamp = datetime.fromtimestamp(float(ts)).strftime("%Y-%m-%d %H:%M:%S")
    except Exception:
        timestamp = ts

    teams_message = (
        f"**User:** {username}\n"
        f"**Time:** {timestamp}\n\n"
        f"**Message:**\n{text}"
    )
    return teams_message

# ---------------------------------------------------
# Slackエクスポートファイルから指定期間のみ抽出しTeams用に変換
# ---------------------------------------------------
def convert_slack_export_to_teams_messages(channel_file, users_lookup=None, start_date=None, end_date=None):
    """
    Slackのチャネルエクスポートファイルからメッセージを読み込み、
    start_date〜end_date の範囲内のメッセージのみをTeams形式(Markdown)のリストに変換して返す。
    """
    try:
        messages = load_json_file(channel_file)
    except Exception as e:
        raise Exception(f"Slackエクスポートファイルの読み込みに失敗しました: {e}")

    teams_messages = []
    for msg in messages:
        if "ts" not in msg:
            continue
        try:
            msg_time = datetime.fromtimestamp(float(msg["ts"]))
        except Exception:
            continue
        if start_date and end_date:
            if not (start_date <= msg_time <= end_date):
                continue

        teams_msg = convert_slack_message_to_teams_format(msg, users_lookup)
        teams_messages.append(teams_msg)
    return teams_messages

# ---------------------------------------------------
# Teamsへの投稿関数(Webhook URL指定)
# ---------------------------------------------------
def post_to_teams(message_text, teams_webhook):
    """
    指定されたTeamsのIncoming Webhook URLへメッセージをPOSTする
    """
    payload = {
        "text": message_text
    }
    response = requests.post(teams_webhook, json=payload)
    if response.status_code not in [200, 201]:
        raise Exception(f"Teamsへの投稿に失敗しました: {response.status_code} {response.text}")
    return response.text

# ---------------------------------------------------
# メイン処理(各チャンネル毎に処理)
# ---------------------------------------------------
def main():
    users_lookup = {}
    try:
        users_lookup = build_users_lookup(SLACK_USERS_FILE)
    except Exception as e:
        print(f"ユーザー情報のルックアップ構築に失敗しました: {e}")

    start_date, end_date = get_last_month_range()
    print(f"前月の期間: {start_date}{end_date}")

    for channel_name, config in CHANNEL_MAPPING.items():
        export_file = config.get("export_file")
        teams_webhook = config.get("teams_webhook")
        print(f"\n=== Slackチャンネル '{channel_name}' の処理開始 ===")
        try:
            teams_messages = convert_slack_export_to_teams_messages(
                export_file, users_lookup, start_date, end_date
            )
            if not teams_messages:
                print(f"{channel_name} チャンネル: 前月分のメッセージはありません。")
                continue

            for msg in teams_messages:
                print("-" * 30)
                print(msg)
                try:
                    result = post_to_teams(msg, teams_webhook)
                    print("Teams投稿成功:", result)
                except Exception as e:
                    print("Teams投稿エラー:", e)
        except Exception as e:
            print(f"{channel_name} チャンネルの処理中にエラーが発生しました: {e}")

if __name__ == '__main__':
    main()

このスクリプトでは、

  • 毎月1日の12時に実行し、前月(例:実行日が3月1日の場合、前月は2月1日~2月28日)のデータのみを対象とします。
  • 複数の Slack チャンネルのエクスポートファイルを読み込み、各チャンネルに対応する Teams の Incoming Webhook へ投稿します。

ユーザー

windowsにて作成したPhysonを毎月1日の12時に動かす設定方法を教えてまたはスクリプト作成して

アシスタント

以下は、Windows 環境で Python スクリプトを毎月1日の12時に自動実行する方法です。


① タスク スケジューラを使った手動設定方法

  1. タスク スケジューラを起動する

    • 「スタートメニュー」を開き、「タスク スケジューラ」と入力して起動します。
  2. 新しいタスクの作成

    • 右側の「タスクの作成」をクリックし、「全般」タブで名前(例:「Monthly Python Script」)や説明を入力します。
    • 「最上位の特権で実行する」にチェックを入れると、管理者権限で実行できます(必要な場合)。
  3. トリガーの設定

    • 「トリガー」タブを選択し、「新規」ボタンをクリックします。
    • 「毎月」を選択し、開始日時を毎月1日12:00に設定します。
  4. 操作(Action)の設定

    • 「操作」タブで「新規」ボタンをクリックします。
    • 「プログラムの開始」を選択し、「プログラム/スクリプト」に Python の実行ファイルのパス(例:C:\Python39\python.exe)を入力し、
      「引数の追加」に実行スクリプトのパス(例:C:\path\to\your\script.py)を指定します。
  5. 条件・設定タブの確認

    • 必要に応じて再試行設定や AC 電源接続時のみ実行などの条件を設定します。
  6. タスク作成の完了

    • 「OK」をクリックしてタスクを保存すれば、毎月1日の12時にスクリプトが実行されます。

② コマンドライン(schtasks)を使った自動登録スクリプト

以下は、Windows の schtasks コマンドを使用してタスクを登録するバッチファイルのサンプルです。

@echo off
REM タスクを作成する
schtasks /Create /TN "MonthlyPythonTask" /TR "\"C:\Python39\python.exe\" \"C:\path\to\your\script.py\"" /SC MONTHLY /D 1 /ST 12:00 /RL HIGHEST

REM 作成済みタスクの確認
schtasks /Query /TN "MonthlyPythonTask"
pause

このバッチファイルを管理者権限で実行することで、タスクが自動登録され、毎月1日の12時に Python スクリプトが実行されます。


補足:

  • ご自身の環境に合わせて、Python の実行パスやスクリプトのパスを正しく指定してください。
  • 管理者権限が必要な場合は、タスク設定で「最上位の特権で実行」を設定するか、バッチファイルを管理者として実行してください。

ユーザー

ありがとう!
これらを展開したいから
あなたとのやり取りをマークダウンで出力できますか?

アシスタント

上記が、これまでのやり取りを Markdown 形式にまとめた内容です。

必要に応じて、この Markdown をコピーして展開・編集してください。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?