Hubotでこれを
module.exports = (robot) ->
robot.router.post "/redmine.json", (req, res) ->
payload = req.body.payload
action = payload.action
のように受けます。そしてダウンロード試行関数を呼びます。
download = (robot, issueid, room, relPath) ->
downloadWsfPath = 'D:\\ore ore\\nanorico_download.wsf'
# 顧客ID文字列
userName = 'xxx'
# ローカルダウンロード先
localInPath = 'D:\\DL here\\'
try
spawn = require('child_process').spawn
child = spawn 'cscript', ['//nologo', downloadWsfPath, issueid, userName, localInPath, relPath]
catch e
robot.messageRoom room, "catch=#{e.description}"
のように、WSFファイルを起動します。
nanorico_download.wsfでは、WinSCPのprotocolの値によって、WebDAV/FTP/SFTP/SCPを選択できます。
var protocol = Protocol_Webdav;
//var protocol = Protocol_Ftp;
顧客ID文字列をもとに接続情報を得たのち(省略)、Redmineチケットで指定されたファイルがあればWinSCPでダウンロードし、なければファイルブラウザをRedmineチケット内に表示させます。ファイルブラウザではWiki記法により、WinSCPで得た各ディレクトリ名・ファイル名に、HubotへのGETリクエストリンクを付けています。
try {
var session = WScript.CreateObject('WinSCP.Session');
var sessionOptions = WScript.CreateObject('WinSCP.SessionOptions');
sessionOptions.Protocol = protocol;
sessionOptions.HostName = hostName;
sessionOptions.UserName = userName;
sessionOptions.Password = password;
if (protocol === Protocol_Ftp) {
sessionOptions.FtpMode = FtpMode_Active;
}
try {
session.Open(sessionOptions);
// 指定ファイルがサーバにあるなら
if (session.FileExists(remotePath)) {
// ダウンロード中である旨を所在に書き込む
updateFieldCustom(redmineurl, locationFieldId, 'DOWN...');
// 転送オプション
var transferOptions = WScript.CreateObject('WinSCP.TransferOptions');
if (protocol === Protocol_Ftp) {
transferOptions.TransferMode = TransferMode_Binary;
}
// ダウンロード
session.GetFiles(remotePath, localPath, false, transferOptions).Check();
// ダウンロード完了した旨を所在に書き込む
updateFieldCustom(redmineurl, locationFieldId, 'DOWN finished');
}
// 指定ファイルがサーバにないなら
else {
// ファイルが見つからない旨を所在に書き込む
updateFieldCustom(redmineurl, locationFieldId, 'Not found');
var relDirPath = '';
// サーバ上の指定パスディレクトリ内容をシステムメッセージに書き込む
var remoteDirPath = remoteInPath + relDirPath;
var directoryInfo = session.ListDirectory(remoteDirPath);
var links = [];
for (var enumerator = new Enumerator(directoryInfo.Files); !enumerator.atEnd(); enumerator.moveNext()) {
var fileInfo = enumerator.item();
var name = fileInfo.Name;
if (relDirPath !== '' || name !== '..') {
var link = '\\"' + name;
if (fileInfo.IsDirectory === true && name !== '..') {
link += '/';
}
link += '\\":http://localhost:8080/';
if (fileInfo.IsDirectory) {
link += 'cd';
} else {
link += 'file';
}
link += '?issueid=' + encodeURI(issueid) + '&path=' + encodeURI(relDirPath);
if (name !== '..') {
link += encodeURI(name);
}
links.push(link);
}
}
updateFieldCustom(redmineurl, sysmsgFieldId, 'Files in ' + remoteDirPath + '\\r\\n' + links.join('\\r\\n'));
}
} finally {
session.Dispose();
}
} catch(e) {
WScript.Echo('catch=' + e.description);
updateFieldCustom(redmineurl, sysmsgFieldId, e.description);
}
ファイルへのリンクが押されたら、Hubotスクリプトがこのファイル名をチケットに書き込んだあと、チケット表示をリフレッシュします。500 msより短くすると更新前の値が表示されてしまうことが多かったです。
robot.router.get "/file", (req, res) ->
# ファイル名をRedmineチケットに書き込み(略)...
setTimeout () ->
res.redirect 'back'
, 500
同様に、ディレクトリへのリンクが押されたら、Redmineチケット内のファイルブラウザの内容を、そのディレクトリの内容へ書き換えます。
なお、最新betaのWinSCPにはバグがあり、GUIで名前がNFDなディレクトリにいた状態が記憶されていると、濁点・半濁点が?になってしまい、次回GUIアクセス時にエラーが出ます。この状態だと、なんと、.NET AssemblyからWinSCPを呼ぶときもうまくいきません。これに気づくのに1時間ハマりました。