以前からFAXをオンラインで確認できるようにしたいと思っていて、数ヶ月前からMattermostを利用し始めたこともあり、Mattermostで受信できるようにしてみた。
複合機が送信したPDF付きメールをGmailで受信し、GASでGoogleDriveからMattermostに投稿してみたが、PDFがサムネイル表示されなかった。ファイル名が自動採番なのでサムネイルは必須であり、そこでPDFからPNGを生成するCloud Runを作成することにした。
Cloud Runを利用し、PDFはGoogleDriveに保存したままPNGをMattermostに投稿、PNGのリンク先にGoogleDriveのPDFを指定することにした。
●Cloud Run
・プロジェクトを作成。
※ここでは、PDF2PNGというプロジェクトを作成した
・Cloud Runというプロダクトを選択し、サービスを作成する
・請求アカウントを作成(請求アカウントがないとサービスが作成できない)
※ここでは、個人クレジットカードというアカウントを作成した
・インラインエディタで関数を作成する
・サービス名:pdf2pngとした
・リージョン:そのまま
・ランタイム:Node.js 20
・承認:未認証の呼び出しを許可
・課金:リクエストベース
・インスタンスの最小数:0
・Ingress:すべて
※Cloud Build APIを有効にする必要があるとでるのでここで有効
・エディタが開くのでindex.js、package.jsonを記入
ベースイメージ: Node.js 20 (Ubuntu 22)を選択
・関数のエントリポイントを空白のまま
※ここを空白にしないとエラーになる
・保存して再デプロイを実施
・URLが表示されるので、変換できるかcurlでテスト
curl -X POST -F “file=@./xxx.pdf” https://xxx.run.app -o output.png
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
const express = require("express"); const multer = require("multer"); const { pdfToPng } = require("pdf-to-png-converter"); const app = express(); const upload = multer({ storage: multer.memoryStorage() }); app.post("/convert", upload.single("file"), async (req, res) => { if (!req.file) return; const pdfBuffer = req.file.buffer; const pngPages = await pdfToPng(pdfBuffer, { viewportScale: 1.0, pages: [1], }); res.setHeader("Content-Type", "image/png"); res.send(pngPages[0].content); }); app.listen(8080, '0.0.0.0'); |
package.json
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "name": "pdf-to-png", "version": "1.0.0", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "express": "^4.18.2", "multer": "^1.4.5-lts.1", "pdf-to-png-converter": "^3.6.3" } } |
GAS(時間トリガーで実行)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
let mattermostUrl = "https://xxx"; let token = "xxx"; let channelId = "xxx"; let folderId = "xxx"; let folder = DriveApp.getFolderById(folderId); let pdf2png = "https://xxx.run.app/convert"; function Main() { let threads = GmailApp.search("is:unread label:inbox subject:Attached Image"); for (let i = 0; i < threads.length; i++) { let messages = threads[i].getMessages(); for (let j = 0; j < messages.length; j++) { let message = messages[j]; if (message.isUnread()){ let attachments = message.getAttachments(); if (attachments.length > 0){ let attachment = attachments[0]; if (attachment.getContentType() == "application/pdf") { CreatePng(attachment); } } message.markRead(); } } } } function CreatePng(attachment){ let file = folder.createFile(attachment); file.setName(attachment.getName()); let fileUrl = file.getUrl(); let formData = { file: file.getBlob() }; const options = { method: "post", payload: formData, muteHttpExceptions: true }; let response = UrlFetchApp.fetch(pdf2png, options); let responseCode = response.getResponseCode(); if (responseCode == 200){ let png = response.getBlob(); PngUploadToMattermost(png,fileUrl) } } function PngUploadToMattermost(attachment,fileUrl) { let formData = { files: attachment } let endpoint = `${mattermostUrl}/api/v4/files?channel_id=${channelId}`; let options = { method: "post", headers: { Authorization: `Bearer ${token}`, }, payload: formData, muteHttpExceptions: true, }; let res = UrlFetchApp.fetch(endpoint, options); PostToMattermost(res,fileUrl); } function PostToMattermost(res,fileUrl){ let info = JSON.parse(res.getContentText()); let fileId = info.file_infos[0].id; let endpoint = `${mattermostUrl}/api/v4/posts`; let payload = { channel_id: channelId, message: `[![PDF](${mattermostUrl}/api/v4/files/${fileId})](${fileUrl})` } let options = { method: "post", headers: { Authorization: `Bearer ${token}`, }, payload: JSON.stringify(payload), muteHttpExceptions: true, }; UrlFetchApp.fetch(endpoint, options); } |