#135 GAS のプロパティサービスには3種類?
はじめに
以下 URL で説明されているように、Google AI Studio で Gemini API を利用するための API キーを取得すれば、GAS のプログラム中から Gemini を利用できるようになります。
現状では、制限はあるものの、無料の Google アカウントでも追加料金なく Gemini API を利用できるようになっていますが、この API キーはそれぞれのアカウントに紐づけられているものなので、
上記 URL の「API キーを安全に保つ」でも、それぞれのユーザーの責任で管理しなければならないことが説明されています。
そのため、この API キーを GAS のプログラム中に直接記述することは適切とは言えません。このような秘匿しなければならない情報を、GAS のプログラム中で扱わなければならないときには、どのように保存しておけばいいのかをまとめてみました。
解決策はプロパティ
GAS が、このような情報を保存するために提供しているのが「プロパティ」です。スクリプトエディタの「プロジェクトの設定」タブの下部に、下図のような「スクリプトプロパティ」と表示されているものです。
上図の「スクリプト プロパティに関するドキュメント」という部分のリンクは、↓ の Properties Service というリファレンスへのリンクとなっています。
この Properties Service で提供されている「Class PropertiesService」を利用することで、
スクリプトプロパティ
ユーザープロパティ
ドキュメントプロパティ
という3種類のプロパティへの情報の読み書きが行えるようになっています。このうち、スクリプトプロパティが前述のようにスクリプトエディタの UI で操作できるようになっています。
廃止される API に注意!
この Properties Service として提供されている API の中には、今後廃止されることが発表されているものがあり、下図のようにリファレンス上で打消し線で表示されているものがあります。
打消し線で表示されている「Class ScriptProperties」を確認すると、非推奨の API であることがページ上部に表示されています。
同様に「Class UserProperties」も非推奨と表示されていますが、これから作るプログラムでは「Class PropertiesService」を用いてアクセスすることが推奨されています。
3つのプロパティの違いは?
この3つのプロパティの違いについて、以下の動画と記事で説明されていました。
要約すると、それぞれで
保存される場所
他のユーザーが参照できるか?
UI で編集できるか?
に違いがあります。この辺りは、↑ の動画の 5:09 あたりからまとめて説明されていますが、いずれのプロパティも「プロジェクト」と表現されているスクリプトに加えて、更に何に紐づけられているか、で違いがある感じ。
プロジェクトに紐づけられていることで…
前項で説明したように、プロパティは「プロジェクト」に紐づけられているのですが、その「プロジェクト」とは何だろう?
スクリプトエディタの「プロジェクトの設定」タブを表示すると、下図のような「スクリプト ID」が表示されている部分があります。
ここで以下のような説明文とともに、「スクリプト ID」なるものが表示されています。
この説明中の「Apps Script プロジェクト」というのは、以下 URL で説明されている「スクリプト プロジェクト」を指していて、これを前述の動画では「プロジェクト」と略していたのです。
↑ の URL の説明中に、↓ のように説明されています。黄色のマーカーを付した部分の文言がわかりやすいのですが、プロジェクトとはスクリプトエディタで開く単位のことを指すのです。
スクリプトエディタで開く単位に紐づいているということは、それぞれの GAS のプログラム(スクリプト)に依存する、ということになります。
自作でライブラリを作ると…
この note ではあまり扱っていませんが、↓ のようにスクリプトエディタの「ライブラリを追加」から自作のライブラリを追加できるようになっています。
↑ の図のように、ライブラリを追加するときは、「スクリプト ID」を指定します。この「スクリプト ID」は、前述のように「プロジェクトの設定」タブで表示されるものです。
この追加できるライブラリについては、わたしの note ではあまり扱っていませんが、↓ の URL で紹介されている方法で、「サービス」のように「ライブラリ」を自作できます。
実際にライブラリを作って確認してみたところ、「ライブラリ」は別の GAS のプログラムとして作成することになるので、「ライブラリ」は別の「プロジェクト」として扱われることになります。
その結果、「ライブラリ」の中でプロパティを扱った場合、「ライブラリ」を呼び出したプロジェクト(プロジェクト)ではなく、「ライブラリ」側のプロジェクトのプロパティに読み書きされてしまいます。
他のユーザーが書き込んだ「ユーザープロパティ」には、他のユーザーがアクセス(読み書き)できない仕様になっているものの、ライブラリのような自身の管理するストレージではない場所に、秘匿しなければならない重要なデータを保存するのは、ちょっとためらうかもしれないなと思ったり…
Gemini API の API キーを保存する場合…
前項までの内容を、表現を変えると以下のようになります。
「スクリプトプロパティ」と「ドキュメントプロパティ」の違いは、次の2点で似ている。
・スクリプトエディタの UI で編集できるか?
・GAS 単体のファイルで利用できるか?「スクリプトプロパティ」と「ドキュメントプロパティ」は、権限のあるユーザーでプロパティを共有できる。
「ドキュメントプロパティ」と「ユーザープロパティ」は、スクリプトエディタの UI でも編集できないので、設定する部分(処理)も GAS のプログラムで用意しなければならない。
「ユーザープロパティ」はユーザーに紐づけられているので、他のユーザーから閲覧できない。しかし、「プロジェクト」にも紐づけられているため、同じユーザーでも異なる GAS のプログラムでは共有できない。
プロパティへのアクセスをライブラリとして共通化した場合、保存したプロパティは作成した GAS の「プロジェクト(プログラム)」ではなく、ライブラリの「プロジェクト」に保存されてしまう。
今回、このように調べはじめたのは、Gemini API の API キーを保存するためだったのですが… プロパティへのアクセスをライブラリ化して、「ユーザープロパティ」に保存すれば、同じライブラリを使えば API キーを管理できるような感じ。
しかしながら、前述したようにそのライブラリを公開して、他のユーザーと共有した場合には、「ユーザープロパティ」はユーザー毎に確保されていて、他のユーザーのプロパティにはアクセスできないはずですが、他人(他のユーザー)の秘匿データを収集してしまっているような感じがして、適切な運用なのか疑問が残る…
自分だけのプログラムとして使うのであれば、API キーをうまく使いまわせるように思うのですが、せっかく作ったプログラムが日の目を見ないのも寂しい…
確認のために作ったプログラム
ちなみに… 今回は、以下のようなプログラムを作成して、動作確認を行いました。getUserProperties() となっている部分を変更すれば、アクセスするプロパティの種類を変更できるので、この辺りを変更して挙動を確認しました。
/*****************************************************************************
* Gemini の API Key については、以下の URL から確認できる
* https://ai.google.dev/gemini-api/docs/api-key?hl=ja
*
* 確認した API Key は、GAS のプロパティに設定し、コピーが作成されても流出・漏洩
* しないようにする。
*/
const GEMINI_API_KEY = 'GEMINI_API_KEY'; // プロパティのプロパティ名
/*****************************************************************************
* @description
* プロパティに Gemini API Key を設定する
* ※引数に与えられた文字列をプロパティに設定する
*
* @param {string} apiKey プロパティに設定する API Key
*/
function setGeminiApiKey(apiKey) {
PropertiesService.getUserProperties().setProperty(GEMINI_API_KEY, apiKey);
}
/*****************************************************************************
* @description
* プロパティに設定されている Gemini API Key を取得する
* ※関数の戻り値にプロパティに設定されている文字列を戻す
*
* @return {string} ロパティに設定された API Key
*/
function getGeminiApiKey() {
return PropertiesService.getUserProperties().getProperty(GEMINI_API_KEY);
}
/*****************************************************************************
* @description
* プロパティに設定されている Gemini API Key を削除する
*/
function deleteGeminiApiKey() {
return PropertiesService.getUserProperties().deleteProperty(GEMINI_API_KEY);
}
/*****************************************************************************
* @description
* プロパティに設定されている Gemini API Key が設定されているかを確認する
*/
function checkGeminiApiKey() {
let apiKey = getGeminiApiKey();
if ((apiKey == '') || (apiKey == null)) {
// スプレッドシートから実行されているのであれば、toast で設定を促す
let ss = SpreadsheetApp.getActiveSpreadsheet();
if (ss != null) {
ss.toast('プロパティに Gemini の API Key を設定してください。');
}
// 設定されていなければ、設定しやすいように、プロパティの項目を設定しておく
setGeminiApiKey('ここに Gemini の API Key を設定します。');
console.log('API Key が設定されていない!');
}
else {
console.log('API Key が設定されている。 [' + apiKey + ']');
}
}
最後に
今回は、プログラムの紹介というより、GAS で提供されている3種類のプロパティの挙動について確認した結果をまとめてみました。用途によって、うまく使い分ければいいのでしょうが、冒頭でふれた Gemini API の API キーを記録する用途だと、どうしたら良いのかはわたし自身も結論を出せていません。😥
最後に、お決まりのフレーズなどを書いておきます。
一応の動作確認は行っているものの、不慮のトラブルによって損害等が生じても、責任はとれませんので予めご了承ください。
実行に際して目的外の場所への書き出しや収集などは行っていません。
特別なエラー処理は行っていないので、意図しないケースでエラーが発生してしまうかもしれません。どうにもならない場合には、ご連絡ください。
わたし自身にしてみると、このような「スクリプトを作ること」が目的になっているような感じですが、このスクリプトが何かの役に立てば幸いです。
これらの記事への感謝の意は、記事に対する「スキ ♡」や、以下のような Amazon のアフィリエイトリンク経由での商品の購入、note の「チップ」機能を利用してもらえると、このようなプログラム作成の励みになります。😍
Amazon のアフィリエイトリンクを開くと、それ以降 24時間以内に商品を購入した場合に、紹介者(この場合は、わたし)に紹介料が発生します。