Last active
March 19, 2020 09:35
-
-
Save shiranuik/d6783773dcaea023cb2a70d56b275c20 to your computer and use it in GitHub Desktop.
GAS+PhantomJSで乗り換え検索してくれるSlackBOT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Naviなんとかさんで経路を検索して教えてくれるSlackBOT | |
//Slack側で必要なこと | |
// スラックアプリを新規作成する | |
// Slash Commandsの設定。 | |
// アプリをワークスペースにインストールする | |
//GAS側の設定・注意するところ | |
// 公開するときは「ウェブアプリケーションとして公開 | |
// 自分が実行 | |
// アクセス可能な人:Anyone,even anonymous | |
// 一度登録した後変更するには、必ず新しいバージョンにして更新すること。 | |
// 使い方( slash commandを /transit として登録した場合 ) | |
// `/transit (到着駅)` or `/transit (出発駅)から(到着駅)` | |
// phantomjsのKey(一日500ページまで) | |
const PhantomJSKey = "PhantomJSのKey"; | |
const slackToken = "SlackのアプリのToken"; | |
function doPost(e){ | |
verification(e.parameter.token); | |
const toStation = e.parameter.text; | |
const userId = e.parameter.user_id; | |
if(toStation==""){ | |
return ContentService.createTextOutput(JSON.stringify({text:"駅名を入力して下さい。"})).setMimeType(ContentService.MimeType.JSON); | |
} | |
addJobQue(toStation,e.parameter.response_url,userId); | |
if(toStation.match(/から/)){ | |
return ContentService.createTextOutput(JSON.stringify({text:toStation+"の経路を検索します。1分〜2分ほどかかりますので少々お待ち下さい。"})).setMimeType(ContentService.MimeType.JSON); | |
} | |
return ContentService.createTextOutput(JSON.stringify({text:"会社から"+toStation+"の経路を検索します。2分〜3分ほどかかりますので少々お待ち下さい。"})).setMimeType(ContentService.MimeType.JSON); | |
} | |
function addJobQue(toStation,responseUrl,userId){ | |
let newQue = { | |
"toStation":toStation, | |
"responseUrl":responseUrl, | |
"userId":userId | |
}; | |
cache = CacheService.getScriptCache(); | |
let data = cache.get("trangit"); | |
if(data==null){ | |
data = []; | |
}else{ | |
data = data.split(";"); | |
} | |
data.push(JSON.stringify(newQue)); | |
// 2分間だけ保存されるキャッシュ。 | |
cache.put("trangit",data.join(";"),60*2); | |
return; | |
} | |
function timeDrivenFunction(){ | |
//cacheの取得 | |
cache = CacheService.getScriptCache(); | |
let data = cache.get("trangit"); | |
if(data==null){ | |
return; | |
}else{ | |
data = data.split(";"); | |
} | |
//長い処理に取り掛かる前に、Jobが複数実行されないようQueは空にしておく。 | |
cache.remove("trangit"); | |
for(let i=0; i<data.length; i++) { | |
data[i] = JSON.parse(data[i]); | |
let response = getTransit(data[i].toStation,data[i].userId); | |
UrlFetchApp.fetch(data[i].responseUrl,{ | |
method: 'post', | |
contentType: 'application/json', | |
payload: JSON.stringify({ | |
text:response | |
}) | |
}); | |
} | |
return; | |
} | |
function getTransit(toStation,userId) { | |
let returnText=""; | |
if(toStation.match(/から/)){ | |
// 出発地の指定がある | |
let KeiroArg = toStation.split("から"); | |
let fromString = KeiroArg[0]; | |
let toString = KeiroArg[1].replace("まで",""); | |
returnText = returnText + searchTransit(fromString,toString); | |
} else { | |
// 指定がないので****からと@@@@からを検索(会社最寄り駅が2つあるので) | |
returnText = returnText + searchTransit("****",toStation); | |
returnText = returnText + searchTransit("@@@@",toStation); | |
} | |
return "<@"+userId+"> "+returnText; | |
//Logger.log(returnText); | |
} | |
function searchTransit(fromStation,toStation){ | |
let searchURL = "https://www.navitime.co.jp/transfer/searchlist?orvStationName="+fromStation+"&dnvStationCode=&thr1StationName=&thr1StationCode=&thr2StationName=&thr2StationCode=&thr3StationName=&thr3StationCode=&basis=1&sort=0&wspeed=100&airplane=0&sprexprs=0&utrexprs=1&othexprs=1&mtrplbus=1&intercitybus=0&ferry=0"; | |
let optionParam = "&dnvStationName="+ toStation; | |
let now = new Date(); | |
// 下に降りる時間があるので出発は5分後にする。 | |
now.setMinutes(now.getMinutes() + 5); | |
let year = Utilities.formatDate(now, 'Asia/Tokyo', 'yyyy'); | |
let month = Utilities.formatDate(now, 'Asia/Tokyo','MM'); | |
let day = Utilities.formatDate(now, 'Asia/Tokyo','dd'); | |
let hour = Utilities.formatDate(now, 'Asia/Tokyo','HH'); | |
let minute = Utilities.formatDate(now, 'Asia/Tokyo','mm'); | |
//さらに5分後の出発で検索するURLのため、念の為すべてを取得 | |
now.setMinutes(now.getMinutes() + 5); | |
let nyear = Utilities.formatDate(now, 'Asia/Tokyo', 'yyyy'); | |
let nmonth = Utilities.formatDate(now, 'Asia/Tokyo','MM'); | |
let nday = Utilities.formatDate(now, 'Asia/Tokyo','dd'); | |
let nhour = Utilities.formatDate(now, 'Asia/Tokyo','HH'); | |
let nminute = Utilities.formatDate(now, 'Asia/Tokyo','mm'); | |
let nextParam = optionParam + '&year='+nyear+'&month'+nmonth+'&day='+nday+'&hour='+nhour+'&minute='+nminute; | |
optionParam = optionParam + '&year='+year+'&month'+month+'&day='+day+'&hour='+hour+'&minute='+minute; | |
let requestParam = { | |
url:searchURL + optionParam, | |
renderType:'HTML', | |
outputAsJson:true}; | |
requestParam = JSON.stringify(requestParam); | |
requestParam = encodeURIComponent(requestParam); | |
let url = 'https://phantomjscloud.com/api/browser/v2/'+PhantomJSKey+'/?request='+requestParam; | |
let response = UrlFetchApp.fetch(url); | |
let json = JSON.parse(response.getContentText()); | |
let content = json["content"]["data"]; | |
let result = content.match(/name="routeText".*?【1】/g); | |
let returnText = fromStation+"から"+toStation+"の検索\n"; | |
if(Array.isArray(result)){ | |
result.forEach(function(r){ | |
returnText = returnText + r.replace('name="routeText" value="',"").replace("【1】","").replace("回<br>","回 ").replace("分<br>","分 ").replace("円<br>","円").replace(/<br>/g,"\n") + "\n----\n"; | |
}); | |
returnText = returnText + "<"+searchURL+nextParam+"|"+fromStation+"を"+nminute+"分に出発で検索>\n=====\n"; | |
}else{ | |
returnText = returnText + "検索結果は0件でした。駅名が正しくない可能性があります。\n"; | |
} | |
return returnText; | |
} | |
//tokenCheck | |
function verification(token){ | |
if( token != slackToken ){ | |
throw new Error('invalid token'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment