はじめに
家のPCで”あるパラメータ”を探していて、日中は講義やら研究室やらにこもってしまうので、その間に家のPCがパラメータを探し終えたかどうかそわそわして中々集中できませんでした。
そこで、パラメータが見つかり次第ファイルを更新するので、そのファイルが更新されたらメールで教えてくれる助手を作ってみました。
大体の流れ
上で説明しているように、ファイル更新をトリガーにしてメールを送信するのを目的としています。また外出時にもファイルの中身が見れるように、メール送信時にファイルをクラウド上にあげてもらいます。
使用したツール当
使用したツール等を簡単に説明します。
1. nodemon (公式: https://nodemon.io/)
以前も紹介しました (以前: ホットリロードで毎回ビルドする方法(nodemon))。
簡単に言うと、フォルダを監視して変更され次第コマンドを叩いてくれます。
今回はこれを監視役として使います。
2. fs
これはJS(TS)のファイルを操作するライブラリです。フォルダの中のファイルを拾ってもらいます。
3. Firebase (Cloud Storage)
更新されたファイルの転送先のクラウドストレージです。選んだ理由としては、個人的に慣れていたからです。今回はストレージのみを使用します。
4. nodemailer
Gmailを送信するためのライブラリです。非常に楽に送信できたので助かりました。
ディレクトリ構成とソースコード
実装したコード等を具体的に紹介しますが、firebaseのconfigファイル等のファイルは見せられないので、Githubには公開していません。
ディレクトリ構成
|
|--node_modules
|--src
| |--utils
| | |--firebase.ts
| | |--config.json
| |
| |--assistant.ts
| |--getFile.ts
| |--mailer.ts
| |--uploader.ts
|--nodemon.json
|--package.json
各コードを紹介していきます。
firebase.ts
firebaseのCloud Storageにアクセスする為のtsファイルです。storageBucket
に自分のCloudStorageのフォルダパスを入力します
import * as firebase from 'firebase-admin'
const serviceAccount = require('./config.json')
firebase.initializeApp({
credential: firebase.credential.cert(serviceAccount),
storageBucket: 'XXXXXXXXXX.appspot.com'
})
export const bucket = firebase.storage().bucket()
getFile.ts
対称のディレクトリにあるファイル名を全て取得してくれるtsファイルです。
取得したいファイル(例:.txt
のみにしたい等)が具体的に決まっている場合はここでフィルターをかけるといいかもしれません。
import * as fs from 'fs'
export const getFileList = (folderPath: string) => {
let fileList: string[] = []
fileList = fs.readdirSync(folderPath)
fileList = fileList.map(file => folderPath + file)
return fileList
}
mailer.ts
メールタイトルと本文を入力するだけでメールを送信してくれるtsファイルです。
sender側のアカウントにここでログインしているので、アカウントの「安全性の低いアプリのアクセス」をオンにしておく必要があります。
import * as mailer from 'nodemailer'
const senderEmail = 'SENDER_EMAIL@gmail.com'
const senderPass = 'SENDERPASS'
const receiverEmail = 'RECEIVER_EMAIL@gmail.com'
const smtpConfig = {
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: senderEmail,
pass: senderPass
}
}
export const mailSend = (title: string, text: string) => {
const smtp = mailer.createTransport(smtpConfig)
const mailOptions = {
from: senderEmail,
to: receiverEmail,
subject: title,
html: text
}
smtp.sendMail(mailOptions, (err, info) => {
if (err) {
console.log(err)
} else {
console.log(`Message sent: ${mailOptions.subject}`)
}
smtp.close()
})
}
uploader.ts
さっき設定したCloud Storageに保存するtsファイルです。アップロードするファイルパスを送るだけで送ってくれます。
import { bucket } from './utils/firebase'
export const uploadFile = (filePath: string) => {
try {
bucket.upload(filePath)
console.log('The file was updated successfully')
} catch (err) {
console.log(err)
}
}
assistant.ts
全体の処理をしてくれるメインファイルです。gmailには簡単なHTMLが埋め込めるとの事なので、アップロードしたファイルをリスト形式<li>
でおくってます。
import { mailSend } from './mailer'
import { getFileList } from './getFile'
import { uploadFile } from './uploader'
const message = (fileList: string[]) => {
const filesText = fileList.map(file => {
return `<li>${file}</li>`
})
return `
<h1>ファイル更新されました</h1>
<h3>以下のファイルが更新されました。https://console.firebase.google.com/u/0/project/XXXXXXXXXXX/storage/XXXXXXXXXXX.appspot.com/files~2F を確認してください。</h3>
<div style="margin: 0.5rem;">
${filesText}
</div>
`
}
const report = () => {
// 監視対象のフォルダ
const targetFolder = './targetFolder/'
// 対称のフォルダにあるファイルを取得
const fileList = getFileList(targetFolder)
// ファイルを全てCould Storageにアップロード
fileList.forEach(file => {
console.log({ file })
uploadFile(file)
})
// 完了メールを送る。
mailSend('ファイルが更新されました。', message(fileList))
}
report()
report()
で対称のフォルダにあるファイルを取得 -> Could Storageにアップロード -> メールを送信をしています。
つまり、監視対象のフォルダが変更され次第このファイルを呼び出せばいいわけですね。
package.json
意外と大事なファイルで、scripts
にコマンドを設定しておくとこの環境元で実行してくれます。
{
"name": "myAssistant",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"report": "ts-node ./src/assistant.ts",
"start": "nodemon"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@types/nodemailer": "^6.2.2",
"firebase-admin": "^8.8.0",
"nodemailer": "^6.3.1",
"nodemon": "^2.0.1",
"ts-node": "^8.5.4",
"typescript": "^3.7.2"
}
}
scripts
を見るとわかりますが、report
でさっきのassistant.ts
を呼び出して、start
でnodemon
を呼び出すことができるようにしています。
nodemon.json
フォルダーを監視して実行してくれる設定ファイルです。
{
"watch": ["./targetFolder/"],
"ext": "*",
"exec": "npm run report"
}
watch
に監視対象のフォルダ、exec
に変更時に実行するコマンドを設定します。
実行例
監視対象フォルダは相対パスでも絶対パスでも可能です。今回はCドライブ直下にtarget
というフォルダを作成してやってみます。
./nodemon.json
とassistant.ts
の監視対象フォルダに設定している箇所をC:\\target\\
に変更します。
そして、コンソールでnodemonを実行します。./package.json
で設定しているstart
を叩きます。
$ npm run start
するとnodemonでassistant.ts
が一度呼び出されます。次に試しに監視対象フォルダであるC:\\target\\
に新しくtestfile.txt
というファイルを作成すると...
> myAssistant@1.0.0 report C:\Users\hogehoge\Documents\workspace\myAssistant
> ts-node ./src/assistant.ts
{ file: 'C:\\target\\testfile.txt' }
The file was updated successfully
Message sent: ファイルが更新されました。
[nodemon] clean exit - waiting for changes before restart
そしてメールが届き
こんなふうに更新されたファイルと保存先のurlまで表示してくれます。
今はファイル作成のときに実行されましたが、もちろんファイル更新時にも実行してくれます。testfile.txt
に"END"と文字を入力して保存すると、同様のメールが届きurlにあるCloud Storageを見てみると...
変更が更新されているのが確認できましたので、これで終わります。
さいごに
助手の名前や本文を変えたり、メールではなくLINEにしたり色々楽しめそうではありますが、時間に余裕がないのでこれで満足しておきます...
出力先のディレクトリを一般向けにしてオープンソースとして公開するという方法もありそうですね。