GASのlinebot で画像を送信する

GASのlinebot で画像を送信する

Google Driveに画像を保存する

保存した画像のタイトルをLINEで返信する
みたいなかんじ?

とりあえず調べたところ
GoogleDriveへ画像を保存し
そのURLを渡して、LINEから送信というかんじみたい

https://developers.line.biz/ja/reference/messaging-api/#wh-image
がリファレンス

https://gas-4u.com/gas16/#index_id1
を参考に
GoogleDriveへ画像保存
それを送信を新しいLINEbotで試す

これにあたり
Googleドライブ上に画像ファイルを一時保存するため、一時保存領域を作成するが
公開されるのはこのディレクトリだけ?
それとも、このディレクトリの上のディレクトリも公開されるかを調べてみる

GPTによれば
Googleドライブで一時保存用のディレクトリを作成し、そのディレクトリだけを公開した場合、
**公開されるのはそのディレクトリとその中のファイル・フォルダのみ** です。
上位のディレクトリ(親ディレクトリ)は公開されません。

### **詳細な動作**
1. **特定のフォルダを公開設定にする**
– そのフォルダの共有設定を「リンクを知っている全員」に設定すると、そのフォルダ以下のファイルやフォルダは公開されます。
– 親フォルダは公開されず、アクセス権を持たないユーザーは親フォルダの存在を認識できません。

2. **親フォルダの共有設定が異なる場合**
– 親フォルダが「非公開」のままで、公開対象のフォルダだけを「リンクを知っている全員」などにすると、そのフォルダ内のファイルのみアクセス可能。
– ただし、親フォルダがすでに「公開」されている場合、その影響を受ける可能性があります。

3. **一時保存ディレクトリの推奨設定**
– **Googleドライブのルート直下に作成する** → 親フォルダの影響を受けにくい。
– **特定の共有フォルダの中に作らない** → 上位フォルダがすでに共有されていると、意図しない範囲が公開される可能性あり。
– **「共有」設定を個別に管理する** → フォルダごとに適切な共有設定をすることで、必要な範囲のみ公開できる。

### **確認方法**
– Googleドライブの共有設定で「このフォルダの上の階層に共有設定があるか」を確認。
– `https://drive.google.com/drive/u/0/my-drive` にアクセスし、フォルダの「詳細情報」→「共有」をチェック。

### **補足**
**もし間違えて親フォルダを公開してしまった場合**、親フォルダの共有設定を見直し、適切に制限をかけることで、意図しない公開を防げます。

適切な設定を行えば、一時保存用のフォルダだけを公開し、それ以上の階層が公開される心配はありません。

とのこと

つまりルートディレクトリで作成すれば心配はなさそう

### **🔍 My Drive が公開されていないことを確認する方法**
Googleドライブの「My Drive」全体が誤って公開されていないかを確認するには、以下の方法でチェックできます。

## **✅ 方法 1: 共有設定を確認する(手動)**
1. **Google ドライブを開く**([Google Drive](https://drive.google.com/))
2. 左側の **「マイドライブ」** をクリック
3. **「マイドライブ」直下のフォルダやファイルを1つずつ右クリック → 「共有」** を開く
4. 共有設定の状態を確認:
– **「リンクを知っている全員が閲覧可能」になっていないか**
– **「組織全体で共有」などが設定されていないか**
– **特定のユーザーのみがアクセスできるようになっているか**

📌 **ポイント:**
「マイドライブ」自体は **共有設定ができない** ので、**個別のフォルダやファイルが公開されていないか** を確認する。

## **✅ 方法 2: Google ドライブの「共有アイテム」から確認**
1. **Google ドライブを開く**([Google Drive](https://drive.google.com/))
2. 左側のメニューで **「共有アイテム」** をクリック
3. **自分がオーナーではないフォルダやファイルがあるか確認**
– **不審なフォルダやファイルがないかチェック**
– **公開されているフォルダがあれば、その共有設定を確認**

📌 **ポイント:**
「共有アイテム」内に **意図しない公開フォルダがある場合、設定を変更する** 必要がある。

## **✅ 方法 3: Google ドライブ API を使って公開されているフォルダを一覧取得**
もし大量のフォルダがあり手動で確認が難しい場合、**Google ドライブ API** を使って **「公開されているフォルダ」を一覧取得** できます。

### **📌 Python スクリプトでチェック**

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

# 認証情報のセットアップ(Google Drive API 用のサービスアカウント)
SCOPES = ["https://www.googleapis.com/auth/drive.metadata.readonly"]
SERVICE_ACCOUNT_FILE = "path/to/service_account.json"

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

# 共有されているフォルダを検索
query = "mimeType='application/vnd.google-apps.folder' and sharedWithMe"
results = service.files().list(q=query, fields="files(id, name, owners, webViewLink)").execute()
folders = results.get("files", [])

if not folders:
    print("公開されているフォルダはありません。")
else:
    for folder in folders:
        print(f"フォルダ名: {folder['name']}, URL: {folder['webViewLink']}, 所有者: {folder['owners'][0]['emailAddress']}")

📌 **このスクリプトでできること**
– **「共有されているフォルダ」** を一覧取得
– **「どのメールアドレスがオーナーか」** も確認できる
– **「公開URL」** を取得して意図しないフォルダがないか確認

## **✅ 方法 4: Google Drive の「詳細設定」で確認**
Google Drive の **管理コンソール(Google Workspace の場合)** では、すべての公開フォルダを一覧で確認できます。

📌 **Google Drive の管理画面から確認**
1. **Google 管理コンソール**([admin.google.com](https://admin.google.com))を開く
2. **「アプリ」→「Google Workspace」→「ドライブとドキュメント」** を選択
3. **「共有設定」** を開く
4. **「外部共有が許可されているフォルダやファイルの一覧」を確認**

👉 これは **Google Workspace(企業用アカウント)** 向けの設定ですが、管理者なら **公開されているフォルダを一括でチェック** できます。

## **✅ 方法 5: 実際に「ログアウトした状態」でアクセスを試す**
1. **Google Chrome の「シークレットモード」を開く**
2. 共有URL(`https://drive.google.com/drive/folders/フォルダID`)を貼り付けてアクセス
3. **「権限がありません」と表示されればOK**(公開されていない)
4. **フォルダが開ける場合は、公開設定を見直す必要あり**

📌 **ポイント:**
– **他のアカウントでアクセスできるか** をテストすると、誤って公開されているかすぐに分かる
– **スマホや別のPCから試す** のも有効

## **🚀 まとめ**
✅ **Google ドライブの「My Drive」自体は共有されないが、フォルダやファイルの個別設定を確認する必要あり**
✅ **「共有アイテム」や「シークレットモードでアクセス」して、意図しない公開がないかチェック**
✅ **大量のフォルダがある場合、Google ドライブ API を使って「公開されているフォルダ一覧」を取得**
✅ **Google Workspace を使っている場合は、管理コンソールで公開フォルダをチェック可能**

この手順で確認すれば、**Google ドライブの個人データが意図せず公開されることは防げます!** 🚀

ということなので
デフォルトは共有されないらしい

ということでmy drive に共有フォルダtmp を作成する

これで
https://drive.google.com/drive/folders/【フォルダID】
ということ

とりあえずこれで準備はOK

次に新しいLINEbot の作成をする

https://gas-4u.com/gas14/#index_id1
を参考に

https://developers.line.biz/console/?status=success
へアクセスし
QRでログイン

公式アカウントを作成する
image_sending

業種を個人、個人その他
運用目的をその他
主な使い道をメッセージ配信用

これで作成

これで公式アカウントはできたので
設定アイコンをクリックし
MessaginAPI を使う

プロバイダー選択し

チャネルシークレット

ユーザID

channelID

Chanel secret
をメモしておく

チャネルシークレット
ユーザIDは
LINE Developers で確認することになる

MessaginAPI の設定で
チャネルアクセストークンを発行

次にGASでの設定

コードは

const REPLY_URL     = 'https://api.line.me/v2/bot/message/reply';
const LINEAPI_TOKEN = '**STEP.1のNo.17で取得したチャネルアクセストークンを記載する**';

/**
 * LINEのトークでメッセージが送信された際に起動するメソッド
 * @param {EventObject} e - イベントオブジェクト
 */
function doPost(e){
  // イベントデータはJSON形式となっているため、parseして取得
  const eventData = JSON.parse(e.postData.contents).events[0]
        , repToken = eventData.replyToken;
  replyTxt(repToken, `LINEへの返信確認`);
}

/**
 * LINEのトークにメッセージを返却するメソッド
 * @param {String} token - メッセージ返却用のtoken
 * @param {String} text - 返却テキスト
 */
function replyTxt(token, txt){
  const message = {
                    'replyToken' : token,
                    'messages' : [{
                      'type': 'text',
                      'text': txt
                    }]
                  }
        , options = {
                    'method' : 'post',
                    'headers' : {
                      'Content-Type': 'application/json; charset=UTF-8',
                      'Authorization': 'Bearer ' + LINEAPI_TOKEN,
                    },
                    'payload' : JSON.stringify(message)
                  };
  UrlFetchApp.fetch(REPLY_URL, options);
}

これを

mkdir gas_iamge_bot 
cd gas_iamge_bot 


保存しておく

また
https://script.google.com/home
へアクセスし
新しいプロジェクトを作成

またこのままだとセキュリティリスクがあるので
スクリプトプロパティの設定をして
LINEAPI_TOKEN に LINE のチャネルアクセストークンを登録

値にはチャネルアクセストークンを入れる

そして

const LINEAPI_TOKEN = PropertiesService.getScriptProperties().getProperty('LINEAPI_TOKEN');

というようにトークン読み込み方法を変更する

そしてデプロイ
この時にデプロイタイプを聞かれるので
ウェブアプリを選択

新しい説明文には
画像送信ボット

アクセスユーザを全員に変更

このURLをweb hook に設定

また応答設定で
Webhookを有効にするのを忘れずに

応答メッセージ
応答時間
はオフにする

これでスマホからメッセージを送信して
自動返信ができれば
とりあえずの動作確認はOK

次に画像を送信するようにしていく

これを改良して GASを使い linebot を webhookで動作させる python でbot 画像を送信する というようにしたい なお、メッセージの受信した時に反応するのではなく 定期的にlinebot で画像を送信するbot にしたい

✅ 設計概要
* Google Apps Script(GAS)
* Webhook(エンドポイント)として動作する(メッセージを受信するが、反応しない)。
* 外部からリクエストを受けた際に LINE Bot で画像を送信する。
* Python
* 定期的に GAS のエンドポイントへリクエストを送信(Google Cloud Scheduler や cron で定期実行)。
* GAS のエンドポイントに 送信したい画像URLとメッセージをPOST する。

GAS は Webhook エンドポイント として動作し、Python からのリクエストを受けて LINE に画像を送信 する。

const LINEAPI_TOKEN = PropertiesService.getScriptProperties().getProperty('LINEAPI_TOKEN');
const PUSH_URL = 'https://api.line.me/v2/bot/message/push';

/**
 * Webhook (Pythonからリクエストを受け取る)
 * @param {Object} e - HTTP POST リクエスト
 * @returns {ContentService} - 成功・失敗のレスポンス
 */
function doPost(e) {
  try {
    const requestData = JSON.parse(e.postData.contents);
    const userId = requestData.userId;  // 送信先のLINEユーザーID
    const imageUrl = requestData.imageUrl;  // 送信する画像URL
    const message = requestData.message;  // 画像と一緒に送るテキスト

    if (!userId || !imageUrl) {
      throw new Error("userId または imageUrl がありません");
    }

    sendImageToLine(userId, imageUrl, message);
    return ContentService.createTextOutput(JSON.stringify({ status: "success" })).setMimeType(ContentService.MimeType.JSON);
  } catch (error) {
    console.error(error);
    return ContentService.createTextOutput(JSON.stringify({ status: "error", message: error.message })).setMimeType(ContentService.MimeType.JSON);
  }
}

/**
 * LINE に画像メッセージを送信
 * @param {string} userId - 送信先の LINE ユーザーID
 * @param {string} imageUrl - 送信する画像URL
 * @param {string} message - 画像と一緒に送るテキスト
 */
function sendImageToLine(userId, imageUrl, message) {
  const payload = {
    "to": userId,
    "messages": [
      {
        "type": "text",
        "text": message
      },
      {
        "type": "image",
        "originalContentUrl": imageUrl,
        "previewImageUrl": imageUrl
      }
    ]
  };

  const options = {
    "method": "post",
    "headers": {
      "Content-Type": "application/json",
      "Authorization": "Bearer " + LINEAPI_TOKEN
    },
    "payload": JSON.stringify(payload)
  };

  const response = UrlFetchApp.fetch(PUSH_URL, options);
  console.log("LINE送信結果: " + response.getContentText());
}

次に画像送信するpythonコード

vim image_bot.py

import requests
import json

# GAS の Webhook エンドポイント(GAS のデプロイ URL)
GAS_WEBHOOK_URL = "https://script.google.com/macros/s/XXXXXXXX/exec"

# 送信する LINE ユーザーID(LINE Developers で取得)
LINE_USER_ID = "Uxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# 送信する画像URL(Google Drive / Web上の画像)
IMAGE_URL = "https://example.com/path/to/image.jpg"

# 画像と一緒に送るメッセージ
MESSAGE = "こちらが最新の画像です!"

def send_image():
    payload = {
        "userId": LINE_USER_ID,
        "imageUrl": IMAGE_URL,
        "message": MESSAGE
    }

    headers = {"Content-Type": "application/json"}
    response = requests.post(GAS_WEBHOOK_URL, data=json.dumps(payload), headers=headers)

    if response.status_code == 200:
        print("送信成功:", response.json())
    else:
        print("送信失敗:", response.text)

if __name__ == "__main__":
    send_image()

これをさらにgoogle drive の画像を送信するようにしたい

コメントを残す

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