diff --git a/.gitignore b/.gitignore index 3c3629e..1af3be6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ node_modules +capture.jpg +.envrc +token.json \ No newline at end of file diff --git a/README.md b/README.md index 9fc6b65..079fa9e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,33 @@ # bushitsuchan-PC OSKの部室の様子を様子をオンラインで確認できるプロジェクト 部室ちゃん. -その部室に置いてあるPC側で動かすプログラム. \ No newline at end of file +その部室に置いてあるPC側で動かすプログラム. + +## Google Photos APIs を使えようにする +1. [Photos Library API](https://console.developers.google.com/apis/library/photoslibrary.googleapis.com)を有効にする. +1. [認証情報](https://console.developers.google.com/apis/credentials)でOAuth クライアント IDを作成する (アプリケーションの種類 は その他) +1. 作成した`クライアント ID`と`クライアント シークレット`を`.envrc`に以下のように保存する + +```shell +export client_id="477...oav.apps.googleusercontent.com" +export client_secret="yEP..." +``` +4. `direnv`の有効化方法に従う` +Macでbashなら +```shell +direnv allow +``` + +## カメラを使えるようにする +Macなら +```shell +brew install imagesnap +``` +Ubuntuは +```shell +sudo apt-get install fswebcam +``` + +## Usage +1. `npm install` +1. `npm start` +を実行 \ No newline at end of file diff --git a/app.js b/app.js index 3918c74..5d1af7c 100644 --- a/app.js +++ b/app.js @@ -1 +1,59 @@ "use strict"; + +const photoapi = require("./photoAPI"); +const {capture} = require("./caputure"); +const slack = require("./slack"); + +const main = async () => { + //認証鍵の設定 + const {client_id, client_secret} = process.env; + if (!client_id || !client_secret) { + console.log("READMEに従ってGoogle Photos APIsの認証鍵を設定してください"); + process.exit(1) + } + const oAuth2Client = await photoapi.getOAuthToken(client_id, client_secret); + + //共有するためアルバムを指定 + const albumTitle = "bushitsuchan_album"; + const albums = await photoapi.getAlbumList(oAuth2Client); + let album = albums.filter((album) => album.title === albumTitle)[0]; + + if (album === undefined) { + album = await photoapi.createAlbum(oAuth2Client, albumTitle); + await photoapi.shareAlbum(oAuth2Client, album.id) + } + + //定期的に撮影した写真の共有リンクをslackbotで送信 + //https://developers.google.com/photos/library/guides/api-limits-quotas に抵触しないように!! + /** + * 何msに一回実行するか あまり小さくしすぎるとエラーが発生します + * @type {number} + */ + const interval = 10 * 1000; + if (60 * 60 * 24 * 1000 / 10000 * 3 > interval) { + console.log(`注意: 1日あたり${(60 * 60 * 24 * 3 / interval * 1000).toLocaleString()}回PhotoAPIを叩く設定で,1日の上限10,000回を越してしまいます`) + } + setInterval(async () => { + const url = await capture(oAuth2Client, album).catch(e => { + console.error(e.name); + if (e.name === "StatusCodeError") { + console.error(JSON.parse(e.error).error.message); + return + } + console.error(e.message) + // console.error(e) + }); + if (!url) { + return + } + const shortURL = await photoapi.getShortURL(url); + + // ここをカスタマイズしてください + slack.send(shortURL) + }, interval) +}; + + +if (require.main === module) { + main().catch(console.error) +} \ No newline at end of file diff --git a/caputure.js b/caputure.js new file mode 100644 index 0000000..406d0db --- /dev/null +++ b/caputure.js @@ -0,0 +1,45 @@ +"use strict"; + +const photoapi = require("./photoAPI"); +const NodeWebcam = require('node-webcam'); +const slack = require("./slack"); + + +const Webcam = NodeWebcam.create({ + width: 1280, + height: 720, + quality: 100, + + delay: 0, + saveShots: true, + device: false, + callbackReturn: "buffer", + verbose: false +}); + +/** + * 写真を撮影しGooglePhotoへとアップロード,その共有リンクを取得します + * @param {oAuth2Client} oAuth2Client - photoapi.getOAuthToken関数で取得します + * @param {Object} album + * @returns {Promise} + */ +module.exports.capture = async (oAuth2Client, album) => { + const photo = await new Promise((resolve, reject) => { + Webcam.capture("capture", (err, photo) => { + if (err) { + reject(err) + } + resolve(photo) + }) + }).catch(e => { + console.error(e); + console.error( + "READMEに従ってカメラを使えるようにしてください\n" + + "また,OSやセキュリティソフトでカメラへのアクセスをブロックしている可能性もあります 解除してください\n"); + process.exit(1) + }); + const uploadToken = await photoapi.uploadPhoto(oAuth2Client, photo, Date().toLocaleString()); + const {mediaItem} = await photoapi.createAlbumMediaItem(oAuth2Client, album.id, uploadToken, ""); + const {baseUrl} = await photoapi.getMediaItem(oAuth2Client, mediaItem.id); + return baseUrl +}; \ No newline at end of file diff --git a/oauth2.keys.json b/oauth2.keys.json new file mode 100644 index 0000000..3a0711a --- /dev/null +++ b/oauth2.keys.json @@ -0,0 +1,6 @@ +{ + "web": { + "client_id": "", + "client_secret": "" + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 54dcaa0..d3e6f1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,686 @@ { "name": "bushitsuchan-pc", "version": "1.0.0", - "lockfileVersion": 1 + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", + "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "axios": { + "version": "0.18.0", + "resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "requires": { + "follow-redirects": "^1.3.0", + "is-buffer": "^1.1.5" + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", + "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "es6-promise": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "gcp-metadata": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.7.0.tgz", + "integrity": "sha512-ffjC09amcDWjh3VZdkDngIo7WoluyC5Ag9PAYxZbmQLOLNI8lvPtoKTSCyU54j2gwy5roZh6sSMTfkY2ct7K3g==", + "requires": { + "axios": "^0.18.0", + "extend": "^3.0.1", + "retry-axios": "0.3.2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "google-auth-library": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-2.0.1.tgz", + "integrity": "sha512-CWLKZxqYw4SE+fE3GWbVT9r/10h75w8lB3cdmmLpLtCfccFDcsI84qI5rx7npemlrHtKJh3C2HUz4s6SihCeIQ==", + "requires": { + "axios": "^0.18.0", + "gcp-metadata": "^0.7.0", + "gtoken": "^2.3.0", + "https-proxy-agent": "^2.2.1", + "jws": "^3.1.5", + "lodash.isstring": "^4.0.1", + "lru-cache": "^4.1.3", + "semver": "^5.5.0" + } + }, + "google-p12-pem": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/google-p12-pem/-/google-p12-pem-1.0.2.tgz", + "integrity": "sha512-+EuKr4CLlGsnXx4XIJIVkcKYrsa2xkAmCvxRhX2HsazJzUBAJ35wARGeApHUn4nNfPD03Vl057FskNr20VaCyg==", + "requires": { + "node-forge": "^0.7.4", + "pify": "^3.0.0" + } + }, + "googleapis": { + "version": "35.0.0", + "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-35.0.0.tgz", + "integrity": "sha512-HseVyK5CVwFM+x+uHqkbKxDRuaMVkYyfAM7Buz3X44/BglHWtzOrtffRVoQORLQHVf4kzhJcjmUvVTwfOG6klA==", + "requires": { + "google-auth-library": "^2.0.0", + "googleapis-common": "^0.4.0" + } + }, + "googleapis-common": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-0.4.0.tgz", + "integrity": "sha512-G8U5eUhmCzvZa80BtfcL2ECPiIJxmJYsPPIY3/9iODrIvDkY75wtxnEobG7HDUprtn/3Es6mP6KevqNZ5u6t4g==", + "requires": { + "axios": "^0.18.0", + "google-auth-library": "^2.0.0", + "pify": "^4.0.0", + "qs": "^6.5.2", + "url-template": "^2.0.8", + "uuid": "^3.2.1" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, + "gtoken": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/gtoken/-/gtoken-2.3.0.tgz", + "integrity": "sha512-Jc9/8mV630cZE9FC5tIlJCZNdUjwunvlwOtCz6IDlaiB4Sz68ki29a1+q97sWTnTYroiuF9B135rod9zrQdHLw==", + "requires": { + "axios": "^0.18.0", + "google-p12-pem": "^1.0.0", + "jws": "^3.1.4", + "mime": "^2.2.0", + "pify": "^3.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jwa": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz", + "integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.10", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz", + "integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==", + "requires": { + "jwa": "^1.1.5", + "safe-buffer": "^5.0.1" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==" + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "~1.37.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node-forge": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", + "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==" + }, + "node-webcam": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/node-webcam/-/node-webcam-0.4.6.tgz", + "integrity": "sha512-TSiTag0jhTlWralSuX3MDbQtagQN/covkZI6S8Ie2gT/xthsmVdBA+GnJVeVLDIeqTKVsl90lsy8vYiLWMVx4w==", + "requires": { + "nopt": "*" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", + "requires": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.6.0.tgz", + "integrity": "sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA==" + }, + "readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw=" + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + } + } + }, + "request-promise": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz", + "integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=", + "requires": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.1", + "stealthy-require": "^1.1.0", + "tough-cookie": ">=2.3.3" + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "requires": { + "lodash": "^4.13.1" + } + }, + "retry-axios": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-0.3.2.tgz", + "integrity": "sha512-jp4YlI0qyDFfXiXGhkCOliBN1G7fRH03Nqy8YdShzGqbY5/9S2x/IR6C88ls2DFkbWuL3ASkP7QD3pVrNpPgwQ==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + }, + "sshpk": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", + "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "url-template": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", + "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } } diff --git a/package.json b/package.json index 17c1619..a9ce858 100644 --- a/package.json +++ b/package.json @@ -16,5 +16,13 @@ "bugs": { "url": "https://github.com/TUS-OSK/bushitsuchan-PC/issues" }, - "homepage": "https://github.com/TUS-OSK/bushitsuchan-PC#readme" + "homepage": "https://github.com/TUS-OSK/bushitsuchan-PC#readme", + "dependencies": { + "googleapis": "^35.0.0", + "node-webcam": "^0.4.6", + "path": "^0.12.7", + "readline": "^1.3.0", + "request": "^2.88.0", + "request-promise": "^4.2.2" + } } diff --git a/photoAPI.js b/photoAPI.js new file mode 100644 index 0000000..79d9d36 --- /dev/null +++ b/photoAPI.js @@ -0,0 +1,300 @@ +"use strict"; + +const fs = require("fs"); +const {google} = require("googleapis"); +const readline = require("readline"); +const path = require("path"); +const rp = require("request-promise"); +// const assert = require("assert"); + + +const rpap = rp.defaults({ + "transform": (body, response) => { + const constentType = response.headers["content-type"].split("")[0]; + if (constentType === "application/json") { + return JSON.parse(body) + } else if (constentType === "text/plain") { + return body + } else { + return body + } + } +}); + +/** + * @typedef {Object} oAuth2Client + * @property {function: string} getAccessToken + */ + +/** + * 認証鍵を取得します + * @param {string} client_id - GCPで取得したクライアントID + * @param {string} client_secret - GCPで取得したクライアントシークレット + * @returns {Promise} + */ +module.exports.getOAuthToken = (client_id, client_secret) => { + const oAuth2Client = new google.auth.OAuth2( + client_id, + client_secret, + "urn:ietf:wg:oauth:2.0:oob" + ); + const scopes = [ + "https://www.googleapis.com/auth/photoslibrary", + "https://www.googleapis.com/auth/photoslibrary.sharing" + ]; + + const tokenPath = path.join(__dirname, "token.json"); + if (fs.existsSync(tokenPath)) { + oAuth2Client.setCredentials(require(tokenPath)); + return oAuth2Client + } + const authURL = oAuth2Client.generateAuthUrl({ + access_type: "offline", + scope: scopes + }); + + console.log(`以下のサイトを開き,認証したあと表示される文字列をここに貼り付けてください\n${authURL}`); + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + return new Promise(resolve => { + rl.question("入力: ", async authorizationCode => { + rl.close(); + if (authorizationCode === "") { + console.error("入力が無効です 再実行してください"); + process.exit(1) + } + const {tokens} = await oAuth2Client.getToken(authorizationCode); + oAuth2Client.setCredentials(tokens); + fs.writeFileSync(tokenPath, JSON.stringify(tokens)); + resolve(oAuth2Client) + }) + }) +}; + + +/** + * アルバム一覧の取得 + * @param {oAuth2Client} oAuth2Client - getOAuthToken関数で取得します + * @returns {Promise>} + */ +module.exports.getAlbumList = async oAuth2Client => { + const accessToken = await oAuth2Client.getAccessToken(); + const url = "https://photoslibrary.googleapis.com/v1/albums"; + const headers = { + "Content-type": "application/json", + Authorization: `Bearer ${accessToken.token}` + }; + return rpap(url, { + method: "GET", + headers: headers + }) + .then(response => response["albums"]) +}; + + +/** + * 画像のバイナリデータを送信します + * @param {oAuth2Client} oAuth2Client - getOAuthToken関数で取得します + * @param photo + * @param {string} filename + * @returns {Promise} uploadToken + */ +module.exports.uploadPhoto = async (oAuth2Client, photo, filename) => { + const accessToken = await oAuth2Client.getAccessToken(); + const url = "https://photoslibrary.googleapis.com/v1/uploads"; + const headers = { + Authorization: `Bearer ${accessToken.token}`, + "Content-type": "application/octet-stream", + "X-Goog-Upload-File-Name": filename, + "X-Goog-Upload-Protocol": "raw" + }; + return rpap(url, { + method: "POST", + headers: headers, + body: photo + }) +}; + + +/** + * アップロードした画像を単なる写真として保存します + * @param {oAuth2Client} oAuth2Client - getOAuthToken関数で取得します + * @param {string} uploadToken - uploadPhoto関数で取得します + * @param {string} description + * @returns {Promise>} + */ +module.exports.createMediaItem = async (oAuth2Client, uploadToken, description) => { + const accessToken = await oAuth2Client.getAccessToken(); + const url = "https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate"; + const headers = { + "Content-type": "application/json", + Authorization: `Bearer ${accessToken.token}` + }; + const body = { + "newMediaItems": [ + { + "description": description, + "simpleMediaItem": { + "uploadToken": uploadToken + } + } + ] + }; + return rpap(url, { + method: "POST", + headers: headers, + body: JSON.stringify(body) + }) + .then(response => response["newMediaItemResults"]) +}; + + +/** + * アップロードした画像をアルバムに追加します + * @param {oAuth2Client} oAuth2Client - getOAuthToken関数で取得します + * @param {string} albumID + * @param {string} uploadToken - uploadPhoto関数で取得します + * @param {string} description + * @returns {Promise} + */ +module.exports.createAlbumMediaItem = async (oAuth2Client, albumID, uploadToken, description) => { + const accessToken = await oAuth2Client.getAccessToken(); + const url = "https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate"; + const headers = { + "Content-type": "application/json", + Authorization: `Bearer ${accessToken.token}` + }; + const body = { + "albumId": albumID, + "newMediaItems": [ + { + "description": description, + "simpleMediaItem": { + "uploadToken": uploadToken + } + } + ] + }; + return rpap(url, { + method: "POST", + headers: headers, + body: JSON.stringify(body) + }) + .then(response => response["newMediaItemResults"][0]) +}; + + +/** + * アルバムを作成します + * @param {oAuth2Client} oAuth2Client - getOAuthToken関数で取得します + * @param {string} title + * @returns {Promise} + */ +module.exports.createAlbum = async (oAuth2Client, title) => { + const accessToken = await oAuth2Client.getAccessToken(); + const url = "https://photoslibrary.googleapis.com/v1/albums"; + const headers = { + "Constent-type": "application/json", + Authorization: `Bearer ${accessToken.token}` + }; + const body = { + album: { + title: title + } + }; + return rpap(url, { + method: "POST", + headers: headers, + body: JSON.stringify(body) + }) +}; + +/** + * アルバムを共有します + * @param {oAuth2Client} oAuth2Client - getOAuthToken関数で取得します + * @param {string} albumID + * @returns {Promise} + */ +module.exports.shareAlbum = async (oAuth2Client, albumID) => { + const accessToken = await oAuth2Client.getAccessToken(); + const url = `https://photoslibrary.googleapis.com/v1/albums/${albumID}:share`; + const headers = { + "Constent-type": "application/json", + Authorization: `Bearer ${accessToken.token}` + }; + const body = { + "sharedAlbumOptions": { + "isCollaborative": "true", + "isCommentable": "true" + } + }; + return rpap(url, { + method: "POST", + headers: headers, + body: JSON.stringify(body) + }) +}; + + +/** + * アップロード済みの写真に関する情報を取得します + * @param {oAuth2Client} oAuth2Client - getOAuthToken関数で取得します + * @param {string} mediaItemID + * @returns {Promise} + */ +module.exports.getMediaItem = async (oAuth2Client, mediaItemID) => { + const accessToken = await oAuth2Client.getAccessToken(); + const url = `https://photoslibrary.googleapis.com/v1/mediaItems/${mediaItemID}`; + const headers = { + "Constent-type": "application/json", + Authorization: `Bearer ${accessToken.token}` + }; + return rpap(url, { + method: "GET", + headers: headers, + }) +}; + +/** + * 与えられたURLの短縮URLを取得します + * @param {string} url + * @returns {Promise} 短縮URL + */ +module.exports.getShortURL = url => { + return rpap.get(`http://is.gd/create.php?format=simple&format=json&url=${url}`) + .then(result => JSON.parse(result)["shorturl"]) +}; + +async function main() { + const {client_id, client_secret} = process.env; + if (!client_id || !client_secret) { + console.log("READMEに従ってGoogle Photos APIsの認証鍵を設定してください"); + process.exit(1) + } + const oAuth2Client = await module.exports.getOAuthToken(client_id, client_secret); + + const albumTitle = "bushitsuchan_test_album"; + const albums = await module.exports.getAlbumList(oAuth2Client); + let album = albums.filter((album) => album.title === albumTitle)[0]; + if (album === undefined) { + album = await module.exports.createAlbum(oAuth2Client, albumTitle); + await module.exports.shareAlbum(oAuth2Client, album.id) + } + + const filename = "example.png"; + if (!fs.existsSync(filename)) { + console.error(`${filename}が存在しないのでアップロードできません`); + process.exit(1) + } + const uploadToken = await module.exports.uploadPhoto(oAuth2Client, fs.createReadStream(filename), filename); + const {mediaItem} = await module.exports.createAlbumMediaItem(oAuth2Client, album.id, uploadToken, ""); + const {baseUrl} = await module.exports.getMediaItem(oAuth2Client, mediaItem.id); + console.log(`共有リンク: ${baseUrl}`) +} + + +if (require.main === module) { + main().catch(console.error) +} \ No newline at end of file diff --git a/slack.js b/slack.js new file mode 100644 index 0000000..eb92dbc --- /dev/null +++ b/slack.js @@ -0,0 +1,6 @@ +"use strict"; + + +module.exports.send = value => { + console.log(`未実装ですが以下を投稿したことになりました ${value}`) +}; \ No newline at end of file