GASを使ってGoogleSlideを画像化してDiscordのWebhookで投稿する
GoogleAppsScriptで画像を動的に生成して、Discordとかに投稿できたら便利だろうなーと思ってちょっと試しに作ってみました。
ただ、課題点も多く限定的な使い方しかできません。
アドベントカレンダーなのに中途半端な記事になってしまって申し訳ないです…
コード全体は以下で確認できます。
実装
事前に画像生成する元の GoogleSlideと生成された画像を保存するフォルダを用意します。
それぞれ、GoogleSlideのID、フォルダのIDを控えておきます。
また、Discordの方もWebhookを作成しておき、トークンを控えておきましょう。
GoogleSlideから画像を生成する
まず、スライドから画像を生成しようと思います。
これはスライドを画像に出力する機能を使います。
以下のようなURLで取得可能です。
https://docs.google.com/presentation/d/${GoogleSlideのID}/export/png?id=${GoogleSlideのID}&pageid=${生成したいスライドのID}
この時GASを実行するアカウントはスライドへのアクセス権が必要なので注意してください。
アクセス権があれば以下のようにヘッダーに認証情報を入れれば取得できます。
const options = {
method: "get",
headers: {"Authorization": `Bearer ${ScriptApp.getOAuthToken()}`},
muteHttpExceptions: true
}
const response = UrlFetchApp.fetch(url, options)
画像をDriveに保存して、公開する
スライドで生成した画像データをDriveに保存します。
先程のレスポンスで画像データを渡されるので、そのBlobデータからファイルを生成します。
const imgBlob = getImageBlob(slide, PRESENTATION_ID)
const file = DriveApp.getFolderById(FOLDER_ID).createFile(imgBlob).setName("date.png")
Discordで表示させるために画像をURLを知ってる人は誰でも閲覧できる状態にします。
これは setSharing
で設定を変更すること実現可能です。
また、画像そのものを表示させたいのでドライブの共有用のURLではなく以下のURLを使用します。
http://drive.google.com/uc?export=view&id=${画像ファイルのID}
Discordに投稿する
DiscordのWebhookを使って投稿します。
Discordへの投稿は embeds
に様々な値を入れることでちょっとした装飾を行った状態で投稿できます。
今回は embeds
に image: {url: imageUrl}
という感じで先程公開した画像のURLを指定します。
すると以下のように表示できます。
課題
一応画像を生成してDiscordに投稿するところまではできたのですがいくつか問題があります。
GASでスライドの内容を変更しても画像化しても編集前の内容になってしまう
今回はスライドをそのまま投稿しましたが、編集したりして投稿できた方が便利です。
しかし、なぜか編集しても編集前の状態で画像化されます。
反映が遅いというわけではなく、今回の画像化する方法だとスクリプト実行中の編集は反映されないみたいです。
動的生成のメリットを最大限に活かすにはどうしても編集したものを生成したいので、これは今後の課題です。
また、今回はGoogleSlideを使いましたが、別のソフトなら上手くできる可能性もあるのでそちらも調べてみてもいいかもしれません。
画像を公開する必要がある
どうしても仕方がないことですが画像を公開する必要があります。URLを知ってる人のみ見れる形式なので注意が必要です。
ただ、Webhookだと画像アップロード用のAPIやフィールドがないのでこれは仕方がないと思います。
おわり
という感じでスライドから画像生成してそれをDiscordまで投稿するという一通りの実装できました。
しかし、編集後のスライドの画像を生成できないと動的に生成するメリットがないので、どう解決するが今後の課題になります。
遅れたうえに未完成で申し訳ないです…!
個人的にGASはエディタもよくなって、GoogleAppと手軽に連帯でき、初心者から玄人まで幅広く使えるのでとても期待しているので、今後もこういった面白いことができないか模索していきたいと思います。
Discussion