Google Drive の画像を linebot へ送信する機能のモジュール化

Google Drive の画像を linebot へ送信する機能のモジュール化

import requests
import random
import time
from googleapiclient.discovery import build
from google.oauth2 import service_account

# ① Google Drive API の設定
SCOPES = ["https://www.googleapis.com/auth/drive"]
SERVICE_ACCOUNT_FILE = "service_account.json"

creds = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
drive_service = build("drive", "v3", credentials=creds)

# ② 送信先の LINE API 設定
LINE_PUSH_URL = "https://api.line.me/v2/bot/message/push"
LINE_CHANNEL_ACCESS_TOKEN = ""

USER_ID = ""


# ③ Google Drive の「temp」フォルダID
FOLDER_ID = ""

def get_drive_images():
    """
    Google Drive の temp フォルダ内の画像リストを取得し、画像の `id` をリストで返す
    """
    query = f"'{FOLDER_ID}' in parents and mimeType contains 'image/' and trashed=false"
    results = drive_service.files().list(q=query, fields="files(id, name)").execute()
    files = results.get("files", [])

    if not files:
        print("No images found in the Drive folder.")
        return None

    return [file["id"] for file in files]

def get_drive_image_url(file_id):
    """
    Google Drive のファイルIDを公開URLに変換する
    """
    try:
        # ファイルのアクセス権限を「公開」に設定
        drive_service.permissions().create(
            fileId=file_id,
            body={"role": "reader", "type": "anyone"},
        ).execute()

        # 画像のダウンロードURLを取得
        return f"https://drive.google.com/thumbnail?id={file_id}&sz=w1000"
    except Exception as e:
        print(f"Error making image public: {e}")
        return None

def send_image(image_url):
    """
    LINE API を使い、取得した画像URLを LINE ユーザーに送信する
    """
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {LINE_CHANNEL_ACCESS_TOKEN}"
    }

    payload = {
        "to": USER_ID,
        "messages": [
            {
                "type": "image",
                "originalContentUrl": image_url,
                "previewImageUrl": image_url
            }
        ]
    }

    response = requests.post(LINE_PUSH_URL, headers=headers, json=payload)
    print(response.status_code, response.text)

def main():
    """
    画像リストを取得し、ランダムな画像を選んでLINEに送信
    """
    image_ids = get_drive_images()
    if not image_ids:
        print("No images found, skipping LINE push.")
        return

    # 画像をランダムに選択
    random_image_id = random.choice(image_ids)
    image_url = get_drive_image_url(random_image_id)

    if image_url:
        # LINE に画像を送信
        send_image(image_url)
    else:
        print("Failed to get a valid image URL.")

# スケジュール実行(30分ごと)
if __name__ == "__main__":
    while True:
        main()
        time.sleep(1800)  # 30分ごとに実行

をモジュールにして文字送信以外に画像も送信可能にする

 vim line_image_sender.py

内容は

import requests
import random
from googleapiclient.discovery import build
from google.oauth2 import service_account

# 設定
SCOPES = ["https://www.googleapis.com/auth/drive"]
SERVICE_ACCOUNT_FILE = "service_account.json"

LINE_PUSH_URL = "https://api.line.me/v2/bot/message/push"
LINE_CHANNEL_ACCESS_TOKEN = "YOUR_LINE_CHANNEL_ACCESS_TOKEN"
USER_ID = "YOUR_LINE_USER_ID"
FOLDER_ID = "YOUR_GOOGLE_DRIVE_FOLDER_ID"

# 認証とサービスの初期化
creds = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
drive_service = build("drive", "v3", credentials=creds)

def get_drive_images(folder_id=FOLDER_ID):
    query = f"'{folder_id}' in parents and mimeType contains 'image/' and trashed=false"
    results = drive_service.files().list(q=query, fields="files(id, name)").execute()
    files = results.get("files", [])
    return [file["id"] for file in files] if files else []

def get_drive_image_url(file_id):
    try:
        drive_service.permissions().create(
            fileId=file_id,
            body={"role": "reader", "type": "anyone"},
        ).execute()
        return f"https://drive.google.com/thumbnail?id={file_id}&sz=w1000"
    except Exception as e:
        print(f"Error making image public: {e}")
        return None

def send_image(image_url, user_id=USER_ID, token=LINE_CHANNEL_ACCESS_TOKEN):
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {token}"
    }
    payload = {
        "to": user_id,
        "messages": [
            {
                "type": "image",
                "originalContentUrl": image_url,
                "previewImageUrl": image_url
            }
        ]
    }
    response = requests.post(LINE_PUSH_URL, headers=headers, json=payload)
    print(response.status_code, response.text)

def send_random_image():
    image_ids = get_drive_images()
    if not image_ids:
        print("No images found.")
        return
    random_image_id = random.choice(image_ids)
    image_url = get_drive_image_url(random_image_id)
    if image_url:
        send_image(image_url)
    else:
        print("Failed to get valid image URL.")

# スクリプトとして直接実行された場合の処理(30分おきに実行)
if __name__ == "__main__":
    import time
    while True:
        send_random_image()
        time.sleep(1800)

これを config.jsonから読み込むようにする

cp ../gas_bot/config.json .

でコピー

{
  "token": "",
  "ollama_model": "elyza:jp8b",
  "line_bot_channel_access_token": "",
  "channel_secret": "",
  "line_bot_user_id": "",
  "google_drive_folder_id": ""
}

というように
Google drive のIDを追加する

import requests
import random
import json
from googleapiclient.discovery import build
from google.oauth2 import service_account

# 設定ファイルの読み込み
with open("config.json", "r") as f:
    config = json.load(f)

LINE_PUSH_URL = "https://api.line.me/v2/bot/message/push"
LINE_CHANNEL_ACCESS_TOKEN = config["line_bot_channel_access_token"]
USER_ID = config["line_bot_user_id"]
FOLDER_ID = config["google_drive_folder_id"]

# Google Drive API の設定
SCOPES = ["https://www.googleapis.com/auth/drive"]
SERVICE_ACCOUNT_FILE = "service_account.json"

creds = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
drive_service = build("drive", "v3", credentials=creds)

def get_drive_images(folder_id=FOLDER_ID):
    query = f"'{folder_id}' in parents and mimeType contains 'image/' and trashed=false"
    results = drive_service.files().list(q=query, fields="files(id, name)").execute()
    files = results.get("files", [])
    return [file["id"] for file in files] if files else []

def get_drive_image_url(file_id):
    try:
        drive_service.permissions().create(
            fileId=file_id,
            body={"role": "reader", "type": "anyone"},
        ).execute()
        return f"https://drive.google.com/thumbnail?id={file_id}&sz=w1000"
    except Exception as e:
        print(f"Error making image public: {e}")
        return None

def send_image(image_url, user_id=USER_ID, token=LINE_CHANNEL_ACCESS_TOKEN):
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {token}"
    }
    payload = {
        "to": user_id,
        "messages": [
            {
                "type": "image",
                "originalContentUrl": image_url,
                "previewImageUrl": image_url
            }
        ]
    }
    response = requests.post(LINE_PUSH_URL, headers=headers, json=payload)
    print(response.status_code, response.text)

def send_random_image():
    image_ids = get_drive_images()
    if not image_ids:
        print("No images found.")
        return
    random_image_id = random.choice(image_ids)
    image_url = get_drive_image_url(random_image_id)
    if image_url:
        send_image(image_url)
    else:
        print("Failed to get valid image URL.")

# スクリプトとして実行されたとき、30分おきに画像送信
if __name__ == "__main__":
    import time
    while True:
        send_random_image()
        time.sleep(1800)

というようにコード変更
これで設定ファイルから読み込むようになる

あとは linebot の画像の管理

これだとどんどん画像が増えていく

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です