LoginSignup
0
2

More than 1 year has passed since last update.

面倒なスクショ作業を自動化してみた!

Posted at

要は

SnapBotという画面変化を検知してスクリーンショット~Slackのスレッドへの送信を自動で行うツールを開発しました。
このBotを使用することで、単純作業であるスクリーンショットのアップロードを自動化し、作業効率を向上させることができます。

こんな感じでスレッド上でスクショを送り続けます。

image.png

Why

なぜこのBotを作ろうと思ったのかというと、勉強会などの機会にスクリーンショットのアップロード作業が手間だったからです。
毎回手動でスクリーンショットを撮影して、それをSlackにアップロードする必要がありました。

What

SnapBotを、作成しました!

  • SlackAppとopenCVを使用して、画面の変化を検知してスクショをアップロードするBot

image.png

このBotを使用することで、スクリーンショットを自動的に取得し、Slackチャンネルにアップロードすることができます。以下に、Botの作成手順を説明します。

How

簡単に技術紹介します。
詳しくはレポジトリを参照してください!

SlackAppを作成

manifest.yamlを使用しました.
漏れやすいポチポチ設定を省けるのでめっちゃ便利。。

とりあえず、ファイルの読み書きを設定しました

display_information:
  name: SnapBot
features:
  bot_user:
    display_name: SnapBot
    always_online: true
oauth_config:
  scopes:
    bot:
      - files:write
      - files:read
settings:
  interactivity:
    is_enabled: true
  org_deploy_enabled: false
  socket_mode_enabled: true
  token_rotation_enabled: false

スクリーンショット

スクリーンショットコマンドを使用しました。

import os

def screenshot():
    os.makedirs("images", exist_ok=True)
    os.system(
        'screencapture -x -o -R0,0,1680,1080 ./images/$(date "+%y%m%d_%H%M%S")_image.png'
    )

直近のスクリーンショットと差分を比較

opencvで画像の特徴量を抽出して差分を定量化しています

import cv2
import numpy as np

THRESHOLD = 10


def judge_image_difference(img1_path, img2_path):
    diff = _image_difference(img1_path, img2_path)
    print(diff)

    return _judge_diff(diff, threshold=THRESHOLD)


def _image_difference(img1_path, img2_path):
    # 画像読み込み
    img1 = cv2.imread(img1_path)
    img2 = cv2.imread(img2_path)

    # 画像をグレースケールに変換
    img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

    # 特徴量抽出器の生成
    orb = cv2.ORB_create()

    # 特徴量の検出と記述子の計算
    _, des1 = orb.detectAndCompute(img1_gray, None)
    _, des2 = orb.detectAndCompute(img2_gray, None)

    # 特徴量のマッチング
    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
    matches = bf.match(des1, des2)

    # マッチングされた特徴点の距離の平均値を計算
    dist_sum = 0
    for match in matches:
        dist_sum += match.distance
    dist_avg = dist_sum / len(matches)

    # 2つの画像の距離を計算
    diff = np.abs(dist_avg)

    return diff


def _judge_diff(diff, threshold=THRESHOLD):
    if diff < threshold:
        return True
    else:
        return False

スレッドへ送信

slack_sdkを使用しました
Slack_Bot_tokenなどの変数は.envに隠蔽しました

import logging
import os
from dotenv import load_dotenv

# Import WebClient from Python SDK (github.com/slackapi/python-slack-sdk)
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

load_dotenv()

# WebClient instantiates a client that can call API methods
# When using Bolt, you can use either `app.client` or the `client` passed to listeners.
client = WebClient(token=os.getenv("SLACK_BOT_TOKEN"))

def send_image_to_thread(is_true, image_path):
    """
    与えられた判定結果と画像を使用して、スレッドに画像を送信する関数。
    判定結果がTrueの場合は、画像をスレッドに送信します。
    """
    if is_true:
        try:
            # Call the files.upload method using the WebClient
            # Uploading files requires the `files:write` scope
            result = client.files_upload_v2(
                channels=os.getenv("CHANNEL_ID"),
                thread_ts=os.getenv("THREAD_TS"),
                file=image_path,
                initial_comment="SNAP :camera:",
            )
            # Log the result
            logger.info(result)
        except SlackApiError as e:
            print(f"Error: {e}")
    else:
        print("判定結果はFalseです。何もしません。")

気づき

  • Slack Appの開発ハードルが低いことを知れた
    • 充実したライブラリとパッケージ
    • manifest.ymlを用いた再現性の高いアプリの構築
  • Slackへのアクションまで一貫すると"自然"に使える
    • 普段から使用するコミュニケーションツール上で動くのは、体験としてめっちゃ良かった

余談1

CopilotとChatGPTが大活躍して数日で要件通り動くものができました
MVPのハードルが下がっているのをめっちゃ感じました

余談2

記事に関しても骨子はChatGPTが作ってくれました、楽ちん

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