目的
Slackのチャンネルにアップされたファイルのバックアップをとるため
事前準備
Slack アプリ設定
- https://api.slack.com/apps から”Create New App”
- AppNameとWorkspaceを指定し,“Create App”
- OAuth&Permissionsへ
- ScopesからBot Token ScopesでAdd an OAuth Scopeでfiles:readを追加
- Install your appからWorkspaceにアプリをインストール
- ダウンロードしたいチャンネルにアプリを追加
.envファイルの設定
.env ファイルを作成
cp .env.example .env
トークンの設定
OAuth&PermissionsのBot User OAuth Tokenをコピーし,TOKEN=の後に張り付け.
チャンネルIDの設定
Slackアプリから,チャンネルのリンクをコピーしURLの末尾のIDをCHANNEL=の後に張り付け
アプリ使用
git clone git@github.com:izumiz-dev/slack-file-downloader.git
npm install
で依存関係をインストール
mkdir downloads
ダウンロードフォルダの作成
npm start
でダウンロード開始
内容説明
- axios
- Slack Web Apis
を使用して作成しました.
ライブラリとして Slack Web API は 必ずしも使用する必要はありませんが,今回はなんとなく使いました.
.envからの読み込み
// OAuth Tokens from .env file
const TOKEN = process.env.SLACK_TOKEN;
const CHANNEL = process.env.CHANNEL;
dotenvというライブラリを用いて,.envファイルから環境変数を読み,nodeスクリプトを実行します.
そのためpackage.json
のscripts
は以下のようになっています.
"scripts": {
"start": "node -r dotenv/config index.js",
}
チャンネルのファイル一覧の取得
指定したチャンネルのファイルのリストを取得します.count
はデフォルトでは100件のため今回は1000にしました.
const res = await web.files.list({
channel: CHANNEL,
count: 1000
})
ファイルダウンロード
まず,取得したファイル一覧のダウンロードリンクと,タイトル名のオブジェクトの配列 downloadFiles
を作成.
const downloadFiles = res.files.map(file => {
return {
url: file.url_private_download,
name: file.name
}
});
次にその配列のオブジェクトにあるダウンロードリンクに対してGETリクエストを送りファイルをダウンロードします.
非同期関数内であるため, Promise.all
の中で map
をし,更に setTimeout
を使い1秒毎にダウンロードするようにしました.
header
に認証情報を渡してあげないとダウンロードできません.responseType
を'stream'
に指定.
リクエスト自体はシンプルです.
const res = await axios({
method: 'get',
url: file.url,
headers: {
Authorization: `Bearer ${TOKEN}`,
},
responseType: 'stream'
});
ダウンロードしたデータを,Node.js のfs.createWriteStream()
によって保存.
const savePath = path.resolve(__dirname, 'downloads', file.name)
console.log(`Saving: ${file.name}`)
res.data.pipe(fs.createWriteStream(savePath))
これで,downloads
フォルダに保存されていきます.
ソースコード
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const { WebClient } = require('@slack/web-api');
// OAuth Tokens from .env file
const TOKEN = process.env.SLACK_TOKEN;
const CHANNEL = process.env.CHANNEL;
const web = new WebClient(TOKEN);
(async () => {
try {
const res = await web.files.list({
channel: CHANNEL,
count: 1000
})
const downloadFiles = res.files.map(file => {
return {
url: file.url_private_download,
name: file.name
}
});
Promise.all(downloadFiles.map(async (file, index) => {
setTimeout(async () => {
const res = await axios({
method: 'get',
url: file.url,
headers: {
Authorization: `Bearer ${TOKEN}`,
},
responseType: 'stream'
});
const savePath = path.resolve(__dirname, 'downloads', file.name)
console.log(`Saving: ${file.name}`)
res.data.pipe(fs.createWriteStream(savePath))
}, 1000 * index)
}))
} catch (error) {
console.log(error);
}
})();
学んだこと
Slack の WebApi は,以前使用したことがありました.
しかし,ファイルの保存は fs.writeFileSync()
くらいしか知らなかったので勉強になりました.
最終的にはググって StackOverFlow をコピペすれば,動くものが作れるのでインターネット様様です😅
参考リンク
- https://api.slack.com/methods/files.list
- https://qiita.com/masakura/items/5683e8e3e655bfda6756
- https://www.npmjs.com/package/dotenv
- https://www.npmjs.com/package/axios