初版作成 2022.3.27
最終更新 2024.04.01
Logger.log() を使う let a = 15; let b = "16"; let contents = "123"; contents = contents + "\n" + "456"; Logger.log(contents); Logger.log("a = " + String(a) + " b = " + b); String( ) を忘れると、エラーは起こらず、それ以降が表示されない というタチが悪い動作をする
let fname = "out.txt"; let contents = "123" + "\n" + "abc"; let rf = DriveApp.getRootFolder(); rf.createFile(fname, contents);
fname = 'out.txt" const contents = DriveApp.getRootFolder().getFilesByName(fname) .next().getBlob().getDataAsString("utf-8"); lines = contents.split('\n'); for(let i = 0; i < lines.length; i++){ Logger.log(lines[i]); }
Google Drive に Google Apps Script 作成する。 そのプログラムを「デプロイ」すると、url が与えられ、 ブラウザでその url にアクセスすると、実行される。 その url を引数なしで GET すると doGet() という コールバック関数が実行され、引数ありで GET すると doGet(e) が実行される。GET するときの引数の有無で コールされる関数が異なるので注意。 POST すると doPost(e) というコールバック関数が実行される。 push するプログラムを定期的に実行するには、 その url を GET すればよい。 reply するプログラムを配置しておけば、line に投稿があったとき 配置したプログラムが実行される。 このサイトが大変わかりやすい。 http://pineplanter.moo.jp/non-it-salaryman/2021/04/23/line-bot-gas/
google drive で 新規 --> その他 --> Google Apps Script 新しいエディタを使う方がやりやすい。 デプロイボタンがある 「関数」のボタンを押して実行する場合、 選択した関数に引数があると、エラーになる。 reply 用の関数を debug のために実行したいときは、 引数なし関数を作成し、その関数内で引数 e を設定し、 doPost(e) を呼ぶ必要があると思われる。 関数を実行しようとすると 認証を要求されるので「権限を確認」をクリックし、 アカウントを選択する。 このアプリは Google で確認されていません と表示される。「詳細」-->「プログラム名(安全でないページに移動)」 で許可をする
デプロイすると url が割り当てられる。 その url を GET あるいは POST すると実行される。 プログラムを変更するたびに新たにデプロイしないと、 更新が有効にならない。 新たにデプロイすると url が変わるので、ちょっと厄介である。 デプロイすると、アプリの種類を聞いてくるので 「ウェブアプリ」を選択し、 アクセスできるユーザーは「全員」に設定する。 push の場合、 doGet() (引数なしに注意)という関数を新設し、 そこから投稿する関数を呼ぶ。 url にアクセスすると doGet() が実行される。
var CHANNEL_ACCESS_TOKEN = 'トークンの内容'; var USER_ID = 'user ID の内容'; function pushMessage() { //deleteTrigger(); var message = "message line"; var postData = { "to": USER_ID, "messages": [{ "type": "text", "text": message, }] }; var url = "https://api.line.me/v2/bot/message/push"; var headers = { "Content-Type": "application/json", 'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN, }; var options = { "method": "post", "headers": headers, "payload": JSON.stringify(postData) }; var response = UrlFetchApp.fetch(url, options); }
https://www.ultra-noob.com/blog/2020/94/ によると、Line に 画像を投稿するには、画像が置いてある https サーバーを 用意する必要がある。 google drive の画像を共有する場合、 image_url = 'https//drive.google.com/uc?id=xxxxxxxx'; という形式で書き、xxxxxxx の部分は、 ファイルのリンクを作成したときに ...file/d/xxxxxxxxxxxxxxxxxx/view?usp=drivesdk の xxxx の部分である。 リンクを作成するときに、リンクを知っている全員が 見れるようにしておく。しかし、Google Drive 上の 画像を使うのは、は以下の 2 点から実用的でない。 (1) リダイレクトするのアドレスなので、 PC 版 Line では見ることができない。 (2) 同名のファイルをアップロードすると、新版が 次々に作成されてゆく。 lolipop は月 100 円程度で借りられるので、 それを使う方がよい。 var CHANNEL_ACCESS_TOKEN = 'トークンの内容'; var USER_ID = 'user ID の内容'; image_url = 'https://xxx.yyy.zzz/dir/image.jpg'; var postData = { "to": USER_ID, "messages": [{ "type": "image", "originalContentUrl": image_url, "previewImageUrl" : image_url }] }; var url = "https://api.line.me/v2/bot/message/push"; var headers = { "Content-Type": "application/json", 'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN, }; var options = { "method": "post", "headers": headers, "payload": JSON.stringify(postData) }; var response = UrlFetchApp.fetch(url, options);
投稿した内容が time なら時刻を返し、 ondo なら現在の温度を返す。 const TOKEN = 'トークン'; function doPost(e) { const responseLine = e.postData.getDataAsString(); const event = JSON.parse(responseLine).events[0]; const replyToken = event.replyToken; let input = event.message.text; let output; let command = input.substr(0, 4); if ( command == "time") { output = "command<" + command + "> now a:b:c"; } else if ( command == "ondo" ){ output = "command<" + command + "> 25 c"; } else { output = "command<" + command + "> no action"; } const LineMessageObject = [{ 'type': 'text', 'text': output }]; const replyHeaders = { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + TOKEN }; const replyBody = { 'replyToken': replyToken, 'messages': LineMessageObject }; const replyOptions = { 'method': 'POST', 'headers': replyHeaders, 'payload': JSON.stringify(replyBody) }; UrlFetchApp.fetch('https://api.line.me/v2/bot/message/reply', replyOptions); }
(1) モジュールのインストール $ pip3 install PyDrive (2) Google 側の設定 https://console.developers.google.com/ 同意して続行する 検索窓に GoogleDriveAPI と入力し、 Google Drive API をクリックし、 「有効にする」をクリックする。 左側の「認証情報」をクリックし、 上側の「認証情報を作成」をクリックする ・OAuth の同意 OAuth 同意画面をクリック 「外部」をクリック アプリ名を入れる メルアドは gmail のアドレスでよいだろう 他は空欄で「保存して次へ」 「テスト」は「アプリを公開」を押す ・認証情報の作成 左側「認証情報」をクリック 上の「認証情報を作成」をクリック 「OAuth クライアントID」 「アプリの種類はデスクトップアプリ」 名前は google-upload 「作成」をクリック クライアント ID, クライアントシークレットが 生成される。この 2 つが必要 json をダウンロードし、 ファイル名を client_secrets.json に変更(これは不要なようだ) ・アップロードすると拒否されるとき https://console.developers.google.com/ から設定を変更する。 OAuth 同意画面 ---> テスト の下の「アプリを公開」をクリック もう一度 upload.py を実行 チェックを入れて「続行」をクリック
settings.yaml を同一ディレクトリに置く ------------ settings.yaml ------------ client_config_backend: settings client_config: client_id: client id を書く client_secret: client_secret を書く save_credentials: True save_credentials_backend: file save_credentials_file: credentials.json get_refresh_token: True oauth_scope: - https://www.googleapis.com/auth/drive.file - https://www.googleapis.com/auth/drive.install ----------- upload.py ------------- #!/usr/bin/python3 # -*- coding: utf-8 -*- from pydrive.auth import GoogleAuth from pydrive.drive import GoogleDrive gauth = GoogleAuth() gauth.LocalWebserverAuth() drive = GoogleDrive(gauth) fname = "a.txt" f_src = open(fname, "r") list = f_src.readlines() f_src.close() contents = "" for i in range(0, len(list)): contents = contents + list[i] print(contents) f_dist = drive.CreateFile({'title': fname}) f_dist.SetContentString(contents) f_dist.Upload()
参考 https://raspi.ryo.sc/python-upload-google-drive/ gauth = GoogleAuth() gauth.CommandLineAuth() drive = GoogleDrive(gauth) fname = "capture.jpg" f = drive.CreateFile({'title': fname, 'mimeType': 'image/jpg'}) # 'parents': [{'drive#fileLink', 'id': FOLDER_ID}]}) f.SetContentFile(fname) f.Upload() url = 'http://drive.google.com/uc?export=view&id=' + f['id'] print(url)
デプロイし、その url を get して実行する。 import urllib.request url = 'https://script.google.com/macros/s/各自のプログラム/exec' req = urllib.request.urlopen(url) page = req.read().decode() lines = page.split('\n') n = len(lines) for i in range(0, n): print(lines[i].rstrip()) GAS のプログラムを変更した場合、 「△実行」を押して実行するなら、変更は反映される。 しかし、url を GET して実行する方法は、 デプロイし直さないと変更が反映されない。 デプロイし直すと url が変更されるので、 厄介である。 2 つのファイルに分けて開発し、doGet() があるファイルを デプロイし、push する内容を決めるファイルが別ファイルに あってもダメ。
Google ドライブにファイル a.txt をアップロードし、 再度 a.txt をアップロードすると、a.txt というファイルが 2 つ存在する状態になる。 Windows 風に解釈すると、表示されるのはショートカット名であり、 ファイル名は異なるが、ショートカット名は同一となる。 100 個に達すると古いものは削除されるらしい。 リンクを生成すると、そのリンクは最新版を指すらしい。
いいかも? https://www.udemy.com/course/web-api-scraping-gas-linebot-tsfcm/
原典 https://tetsuooo.net/gas/42/ // const folder_id = 'xxxxxxx'; // xxxxx は右クリックしてリンクを取得したときの // ...drive/folders/xxxxxxx?usp=sharing の部分 // const folder_obj = DriveApp.getFolderById(folder_id); const folder_obj = DriveApp.getRootFolder(); const files = folder_obj.getFiles(); while(files.hasNext()){ let file = files.next(); let fname = file.getName(); let file_id = file.getId(); let fileURL = file.getUrl(); Logger.log(fname + " " + file_id + " " + fileURL); }