やりたいこと
GoogleAppsScriptを使って自分宛へのメンション
応用すれば別のユーザーへのメンションにも使えるので、
特定のメールが来たら、特定のユーザーにメンションを飛ばすとかが簡単に実装できます。
コード
@google/clasp
を使ってローカル環境でTypeScriptで記載します.
型定義は@type/google-apps-script
を使います
(GASコードも後ろの方で記載します)
メンション用のユーザーIDを取得する
公式リファレンスからGUIでも取得することができます
Method: people.get | People API | Google Developers
↑のリンクを使えば各項目は記載されていますが、一応スクショも記載
GASで取得するとこんな感じ
※マニフェストのスコープを手動で変更する必要があります
oauthScopes
の一つ目はPeopleAPIでmetadataを取得するため、
二つ目はURLFetchを使うためです。
{
"timeZone": "Asia/Tokyo",
"dependencies": {
"enabledAdvancedServices": [
{
"userSymbol": "People",
"version": "v1",
"serviceId": "peopleapi"
}
]
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"oauthScopes": [
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/script.external_request"
]
}
metadata以外のフィールドの取得や、resourceName以外の値については省きます。
↑で記載しているGUIで見た方が早いです
/**
* メンション用のUserIDを取得する
* @returns {string|undefined} userのIDを取得する
*/
const getUserId = (): string | undefined => {
if (People.People) {
const me = People.People?.get("people/me", { personFields: "metadata" });
const { resourceName } = me;
if (resourceName) {
const matchItem = resourceName.match(/^people\/(?<id>[^/]+)$/);
if (matchItem) {
const id = matchItem.groups?.id;
return id;
} else console.warn(`resourceNameが/^people\/[^/]+$/に一致しませんでした\nresourceName: ${resourceName}`);
} else console.warn(`resourceNameが取得できませんでした`);
} else console.warn(`People.Peopleが存在しませんでした`);
return undefined;
};
メンション用の関数
/**
* UserID宛にメンションする
* @param {string} userId - メンションするUserID
* @param {string} botURL - 送信するBOTのWebhookリンク
*/
const notify = (userId: string, botURL: string): void => {
const message = {
text: `俺だよ、俺、<users/${userId}>だよ`,
};
const param: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions & { method: GoogleAppsScript.URL_Fetch.HttpMethod } = {
method: `post`,
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
payload: JSON.stringify(message),
};
UrlFetchApp.fetch(botURL, param);
};
実行用のメイン関数
hookURL
のところはスペースで作ったWebhookのリンクを使ってくださいね
/**
* 実行用の関数
*/
const main = (): void => {
const hookURL = `https://chat.googleapis.com/v1/spaces/SpaceID/messages?key=BotKeys&token=BotToken`;
const userId = getUserId();
if (userId) notify(userId, hookURL);
};
コピペ用
TypeScript
コード
{
"timeZone": "Asia/Tokyo",
"dependencies": {
"enabledAdvancedServices": [
{
"userSymbol": "People",
"version": "v1",
"serviceId": "peopleapi"
}
]
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"oauthScopes": [
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/script.external_request"
]
}
/**
* 実行用の関数
*/
const main = (): void => {
const hookURL = `https://chat.googleapis.com/v1/spaces/SpaceID/messages?key=BotKeys&token=BotToken`;
const userId = getUserId();
if (userId) notify(userId, hookURL);
};
/**
* メンション用のUserIDを取得する
* @returns {string|undefined} userのIDを取得する
*/
const getUserId = (): string | undefined => {
if (People.People) {
const me = People.People?.get("people/me", { personFields: "metadata" });
const { resourceName } = me;
if (resourceName) {
const matchItem = resourceName.match(/^people\/(?<id>[^/]+)$/);
if (matchItem) {
const id = matchItem.groups?.id;
return id;
} else console.warn(`resourceNameが/^people\/[^/]+$/に一致しませんでした\nresourceName: ${resourceName}`);
} else console.warn(`resourceNameが取得できませんでした`);
} else console.warn(`People.Peopleが存在しませんでした`);
return undefined;
};
/**
* UserID宛にメンションする
* @param {string} userId - メンションするUserID
* @param {string} botURL - 送信するBOTのWebhookリンク
*/
const notify = (userId: string, botURL: string): void => {
const message = {
text: `俺だよ、俺、<users/${userId}>だよ`,
};
const param: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions & { method: GoogleAppsScript.URL_Fetch.HttpMethod } = {
method: `post`,
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
payload: JSON.stringify(message),
};
UrlFetchApp.fetch(botURL, param);
};
GAS
コード
{
"timeZone": "Asia/Tokyo",
"dependencies": {
"enabledAdvancedServices": [
{
"userSymbol": "People",
"version": "v1",
"serviceId": "peopleapi"
}
]
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"oauthScopes": [
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/script.external_request"
]
}
/**
* 実行用の関数
*/
const main = () => {
const hookURL = `https://chat.googleapis.com/v1/spaces/SpaceID/messages?key=BotKeys&token=BotToken`;
const userId = getUserId();
if (userId) notify(userId, hookURL);
};
/**
* メンション用のUserIDを取得する
* @returns {string|undefined} userのIDを取得する
*/
const getUserId = () => {
if (People.People) {
const me = People.People?.get("people/me", { personFields: "metadata" });
const { resourceName } = me;
if (resourceName) {
const matchItem = resourceName.match(/^people\/(?<id>[^/]+)$/);
if (matchItem) {
const id = matchItem.groups?.id;
return id;
} else console.warn(`resourceNameが/^people\/[^/]+$/に一致しませんでした\nresourceName: ${resourceName}`);
} else console.warn(`resourceNameが取得できませんでした`);
} else console.warn(`People.Peopleが存在しませんでした`);
return undefined;
};
/**
* UserID宛にメンションする
* @param {string} userId - メンションするUserID
* @param {string} botURL - 送信するBOTのWebhookリンク
*/
const notify = (userId, botURL) => {
const message = {
text: `俺だよ、俺、<users/${userId}>だよ`,
};
const param = {
method: `post`,
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
payload: JSON.stringify(message),
};
UrlFetchApp.fetch(botURL, param);
};
結果
他ユーザーへのメンション
自分以外のUserIDについては管理者ロールを持っていれば取得できそうですが、
私は持っていないため、取得方法は不明。
なので、一般権限のユーザーが、他のユーザーへのメンションを作成する場合は、
前もってメンションするユーザーにIDを取得しておいてもらう必要があるので注意が必要です。
(私の場合は、各自にWebAppにアクセスしてもらい、裏でIDを取得してスプレッドシートに記載されるような仕組みにしました)
試していませんがAdmin SDK APIでも取得できるらしいです
こっちだとメールアドレスで取得できるからこっちの方でしょう、絶対!
Google Chat botがメンションするのに必要なUser IDを開発者コンソールに出力するスクリプト - Qiita
まとめ
ということでお手軽にメンションすることができましたね。
metadataを取得するために、oauthScopes
を自分で記載する必要があることがミソでしょうか。
普段は自動でスコープを与えてくれている分、
いざFetchを使ったり、SpreadSheetを使うと「権限が足りん!」って怒られちゃうので、
その辺は割と面倒だったり。。。
とはいえ、PeopleAPIなんかは特に適当にロール付与しまくるのは怖いので、
ロール管理は学んでおいた方がいいのかもしれない。。。