Skip to content

Commit

Permalink
Merge a5f6b81 into ebb3d44
Browse files Browse the repository at this point in the history
  • Loading branch information
tily committed Sep 1, 2016
2 parents ebb3d44 + a5f6b81 commit 72a0f20
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 28 deletions.
1 change: 1 addition & 0 deletions data/areas.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions data/categories.json
@@ -0,0 +1 @@
{"和食":{"code":"washoku"},"日本料理":{"code":"japanese"},"懐石・会席料理":{"code":"RC010101"},"割烹・小料理":{"code":"RC010103"},"精進料理":{"code":"RC010105"},"京料理":{"code":"RC010104"},"寿司":{"code":"RC010201"},"回転寿司":{"code":"RC010202"},"立ち食い寿司":{"code":"RC010203"},"魚介料理・海鮮料理":{"code":"RC011211"},"ふぐ":{"code":"RC011212"},"かに":{"code":"RC011213"},"すっぽん":{"code":"RC011214"},"あんこう":{"code":"RC011215"},"天ぷら・揚げ物":{"code":"RC0103"},"天ぷら":{"code":"tempura"},"とんかつ":{"code":"tonkatsu"},"串揚げ・串かつ":{"code":"kushiage"},"からあげ":{"code":"RC010304"},"天ぷら・揚げ物(その他)":{"code":"RC010399"},"そば・うどん・麺類":{"code":"RC0104"},"そば":{"code":"soba"},"立ち食いそば":{"code":"RC010408"},"うどん":{"code":"udon"},"カレーうどん":{"code":"RC010407"},"焼きそば":{"code":"RC010406"},"沖縄そば":{"code":"RC010404"},"ほうとう":{"code":"RC010403"},"ちゃんぽん":{"code":"RC010405"},"そば・うどん・麺類(その他)":{"code":"RC010499"},"うなぎ・どじょう・あなご":{"code":"RC0105"},"うなぎ":{"code":"unagi"},"どじょう":{"code":"RC010502"},"あなご":{"code":"RC010503"},"焼鳥・串焼・鳥料理":{"code":"RC0106"},"焼鳥":{"code":"yakitori"},"串焼き":{"code":"RC010602"},"もつ焼き":{"code":"RC010604"},"焼きとん":{"code":"RC010605"},"鳥料理":{"code":"RC010603"},"手羽先":{"code":"RC010606"},"すき焼き・しゃぶしゃぶ":{"code":"RC0107"},"すき焼き":{"code":"RC010701"},"しゃぶしゃぶ":{"code":"syabusyabu"},"豚しゃぶ":{"code":"RC010703"},"おでん":{"code":"RC0108"},"お好み焼き・たこ焼き":{"code":"RC0109"},"お好み焼き":{"code":"okonomiyaki"},"もんじゃ焼き":{"code":"monjya"},"たこ焼き":{"code":"RC010911"},"明石焼き":{"code":"RC010912"},"お好み焼き・たこ焼き(その他)":{"code":"RC010999"},"郷土料理":{"code":"RC0110"},"沖縄料理":{"code":"okinawafood"},"きりたんぽ":{"code":"RC011002"},"郷土料理(その他)":{"code":"RC011099"},"丼もの":{"code":"RC0111"},"牛丼":{"code":"RC011101"},"親子丼":{"code":"RC011102"},"天丼・天重":{"code":"RC011103"},"かつ丼・かつ重":{"code":"RC011104"},"海鮮丼":{"code":"RC011105"},"豚丼":{"code":"RC011106"},"丼もの(その他)":{"code":"RC011199"},"和食(その他)":{"code":"RC019999"},"豆腐料理・湯葉料理":{"code":"RC019910"},"麦とろ":{"code":"RC019908"},"釜飯":{"code":"RC019909"},"もつ料理":{"code":"RC019912"},"くじら料理":{"code":"RC019911"},"牛タン":{"code":"RC019907"},"ろばた焼き":{"code":"RC019903"},"洋食・西洋料理":{"code":"RC02"},"ステーキ・ハンバーグ":{"code":"RC0201"},"ステーキ":{"code":"steak"},"ハンバーグ":{"code":"hamburgersteak"},"鉄板焼き":{"code":"RC0203"},"パスタ・ピザ":{"code":"RC0202"},"パスタ":{"code":"pasta"},"ピザ":{"code":"pizza"},"ハンバーガー":{"code":"hamburger"},"洋食・欧風料理":{"code":"RC0209"},"洋食":{"code":"yoshoku"},"ハヤシライス":{"code":"RC020911"},"オムライス":{"code":"RC020912"},"シチュー":{"code":"RC020913"},"スープ":{"code":"RC020914"},"コロッケ・フライ":{"code":"RC020915"},"洋食・欧風料理(その他)":{"code":"RC020999"},"フレンチ":{"code":"RC021101"},"ビストロ":{"code":"RC021102"},"モダンフレンチ":{"code":"RC021103"},"イタリアン":{"code":"italian"},"スペイン料理":{"code":"RC021301"},"モダンスパニッシュ":{"code":"RC021302"},"西洋各国料理":{"code":"RC0219"},"地中海料理":{"code":"RC021902"},"ドイツ料理":{"code":"RC021903"},"ロシア料理":{"code":"RC021904"},"アメリカ料理":{"code":"RC021905"},"カリフォルニア料理":{"code":"RC021906"},"オセアニア料理":{"code":"RC021907"},"ハワイ料理":{"code":"RC021908"},"西洋各国料理(その他)":{"code":"RC021999"},"中華料理":{"code":"RC030101"},"飲茶・点心":{"code":"RC030102"},"北京料理":{"code":"RC030103"},"上海料理":{"code":"RC030104"},"広東料理":{"code":"RC030105"},"四川料理":{"code":"RC030106"},"台湾料理":{"code":"RC030107"},"餃子・肉まん":{"code":"RC0302"},"餃子":{"code":"gyouza"},"肉まん・中華まん":{"code":"RC030202"},"中華粥":{"code":"RC0303"},"中華麺":{"code":"RC0304"},"担々麺":{"code":"RC030401"},"刀削麺":{"code":"RC030402"},"中華麺(その他)":{"code":"RC030403"},"アジア・エスニック":{"code":"RC04"},"韓国料理":{"code":"RC040101"},"冷麺":{"code":"RC040102"},"東南アジア料理":{"code":"RC0402"},"タイ料理":{"code":"thai"},"ベトナム料理":{"code":"RC040202"},"インドネシア料理":{"code":"RC040203"},"シンガポール料理":{"code":"RC040204"},"東南アジア料理(その他)":{"code":"RC040299"},"南アジア料理":{"code":"RC0403"},"インド料理":{"code":"RC040301"},"ネパール料理":{"code":"RC040302"},"パキスタン料理":{"code":"RC040303"},"スリランカ料理":{"code":"RC040304"},"南アジア料理(その他)":{"code":"RC040399"},"西アジア料理":{"code":"RC0404"},"トルコ料理":{"code":"RC040401"},"西アジア料理(その他)":{"code":"RC040499"},"中南米料理":{"code":"RC0411"},"メキシコ料理":{"code":"RC041101"},"ブラジル料理":{"code":"RC041102"},"中南米料理(その他)":{"code":"RC041199"},"アフリカ料理":{"code":"RC0412"},"アジア・エスニック(その他)":{"code":"RC0499"},"カレー":{"code":"curry"},"カレーライス":{"code":"RC1201"},"欧風カレー":{"code":"RC1202"},"インドカレー":{"code":"RC1203"},"タイカレー":{"code":"RC1204"},"スープカレー":{"code":"RC1205"},"カレー(その他)":{"code":"RC1299"},"焼肉・ホルモン":{"code":"RC1301"},"焼肉":{"code":"yakiniku"},"ホルモン":{"code":"horumon"},"ジンギスカン":{"code":"RC1302"},"鍋":{"code":"nabe"},"ちゃんこ鍋":{"code":"RC1401"},"うどんすき":{"code":"RC1402"},"もつ鍋":{"code":"motsu"},"水炊き":{"code":"RC1404"},"ちりとり鍋・てっちゃん鍋":{"code":"RC1405"},"中国鍋・火鍋":{"code":"RC1406"},"韓国鍋":{"code":"RC1407"},"タイスキ":{"code":"RC1409"},"鍋(その他)":{"code":"RC1408"},"居酒屋・ダイニングバー":{"code":"RC21"},"居酒屋":{"code":"izakaya"},"ダイニングバー":{"code":"RC2102"},"居酒屋・ダイニングバー(その他)":{"code":"RC219999"},"立ち飲み居酒屋・バー":{"code":"RC219902"},"バル・バール":{"code":"RC219903"},"ビアホール・ビアレストラン":{"code":"RC219904"},"創作料理・無国籍料理":{"code":"RC22"},"創作料理":{"code":"RC2201"},"イノベーティブ・フュージョン":{"code":"RC2202"},"無国籍料理":{"code":"RC2203"},"ファミレス":{"code":"RC23"},"レストラン(その他)":{"code":"RC999999"},"定食・食堂":{"code":"RC990101"},"学生食堂":{"code":"RC990102"},"社員食堂":{"code":"RC990103"},"自然食・薬膳":{"code":"RC9903"},"自然食":{"code":"RC990301"},"薬膳":{"code":"RC990302"},"弁当・おにぎり":{"code":"RC9904"},"弁当":{"code":"RC990401"},"おにぎり":{"code":"RC990402"},"バイキング":{"code":"viking"},"デリカテッセン":{"code":"RC999903"},"シーフード":{"code":"RC999901"},"オイスターバー":{"code":"RC999913"},"にんにく料理":{"code":"RC999902"},"野菜料理":{"code":"RC999905"},"牛料理":{"code":"RC999907"},"豚料理":{"code":"RC999908"},"馬肉料理":{"code":"RC999909"},"炭火焼き":{"code":"RC999910"},"バーベキュー":{"code":"RC999911"},"その他肉料理":{"code":"RC999912"},"屋形船・クルージング":{"code":"RC999914"},"ラーメン":{"code":"ramen"},"汁なしラーメン":{"code":"MC21"},"油そば":{"code":"MC2101"},"台湾まぜそば":{"code":"MC2102"},"汁なし担々麺":{"code":"MC2103"},"つけ麺":{"code":"MC11"},"カフェ":{"code":"CC01"},"喫茶店":{"code":"CC02"},"コーヒー専門店":{"code":"CC03"},"紅茶専門店":{"code":"CC04"},"中国茶専門店":{"code":"CC05"},"日本茶専門店":{"code":"CC06"},"カフェ・喫茶(その他)":{"code":"CC99"},"パン・サンドイッチ":{"code":"pan"},"パン":{"code":"SC0101"},"サンドイッチ":{"code":"SC0102"},"ベーグル":{"code":"SC0103"},"パン・サンドイッチ(その他)":{"code":"SC0199"},"スイーツ":{"code":"sweets"},"洋菓子":{"code":"SC0201"},"ケーキ":{"code":"cake"},"チョコレート":{"code":"SC020102"},"マカロン":{"code":"SC020103"},"バームクーヘン":{"code":"SC020104"},"洋菓子(その他)":{"code":"SC020199"},"和菓子・甘味処":{"code":"SC0202"},"和菓子":{"code":"SC020201"},"甘味処":{"code":"SC020202"},"たい焼き・大判焼き":{"code":"SC020203"},"どら焼き":{"code":"SC020204"},"大福":{"code":"SC020205"},"せんべい":{"code":"SC020206"},"中華菓子":{"code":"SC0203"},"スイーツ(その他)":{"code":"SC029999"},"アイスクリーム":{"code":"SC029901"},"ソフトクリーム":{"code":"SC029909"},"かき氷":{"code":"SC029907"},"クレープ":{"code":"SC029903"},"パフェ":{"code":"SC029904"},"フルーツパーラー":{"code":"SC029902"},"ジュースバー":{"code":"SC029905"},"パンケーキ":{"code":"SC029906"},"ドーナツ":{"code":"SC029908"},"フレンチトースト":{"code":"SC029910"},"アサイーボウル":{"code":"SC029911"},"バー":{"code":"BC01"},"パブ":{"code":"BC02"},"ラウンジ":{"code":"BC03"},"ワインバー":{"code":"BC04"},"ビアガーデン":{"code":"BC05"},"ビアバー":{"code":"BC06"},"スポーツバー":{"code":"BC07"},"バー・お酒(その他)":{"code":"BC9999"},"日本酒バー・焼酎バー":{"code":"BC9901"},"日本酒バー":{"code":"BC990101"},"焼酎バー":{"code":"BC990102"},"旅館":{"code":"ryokan"},"オーベルジュ":{"code":"YC02"},"旅館・オーベルジュ(その他)":{"code":"YC99"},"その他":{"code":"ZZ"}}
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -22,7 +22,8 @@
"hubot": ">=2.3.0",
"hubot-scripts": "*",
"request": "*",
"underscore": "*"
"underscore": "*",
"xlsx": "^0.8.0"
},
"devDependencies": {
"blanket": "~1.1.6",
Expand Down
53 changes: 53 additions & 0 deletions script/download
@@ -0,0 +1,53 @@
#!/usr/bin/env node
fs = require('fs')
request = require('request')
cheerio = require('cheerio')
xlsx = require('xlsx')

const categoriesURL = "http://tabelog.com/cat_lst/"
request.get("http://tabelog.com/cat_lst/", (err, res, body)=> {
if(!err && res.statusCode == 200) {
$ = cheerio.load(body)
const mapping = {}
$('table a').each((i, a)=> {
const code = $(a).attr('href').match(/\/rstLst\/(.+)\//)[1]
const name = $(a).text()
console.log(`categories: ${name}: code => ${code}`)
mapping[name] = {code: code}
})
fs.writeFile('data/categories.json', JSON.stringify(mapping))
}
})

const areaURL = "http://www.romanticmissile.com/wp-content/uploads/2013/04/tabelog_area_list.xlsx"
request.get(areaURL, {encoding: null}, (err, res, body)=> {
if(!err && res.statusCode == 200) {
data = new Uint8Array(body)
var arr = new Array()
for(var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i])
var bstr = arr.join("")

const sheet = xlsx.read(bstr, {type: 'binary'}).Sheets['area_list']
const mapping = {}
var code1, code2, code3, city
for(z in sheet) {
if(match = z.match(/^([A-H])/)) {
const col = match[1]
if(col == 'A') {
city = sheet[z].v
} else if (col == 'C') {
code1 = sheet[z].v
} else if (col == 'E') {
code2 = sheet[z].v
} else if(col == 'G') {
code3 = sheet[z].v
} else if (col == 'H') {
const name = sheet[z].v
console.log(`areas: ${name}: city => ${city}, code1 => ${code1}, code2 => ${code2}, code3 => ${code3}`)
mapping[name] = {city: city, code1: code1, code2: code2, code3: code3}
}
}
}
fs.writeFile('data/areas.json', JSON.stringify(mapping))
}
})
57 changes: 41 additions & 16 deletions src/scripts/tabelog.coffee
Expand Up @@ -16,6 +16,9 @@ _ = require 'underscore'
cheerio = require 'cheerio'
request = require 'request'

categories = require '../../data/categories.json'
areas = require '../../data/areas.json'

if proxy = process.env.HUBOT_TABELOG_PROXY
console.log 'proxy: ' + proxy
request = request.defaults {'proxy': proxy}
Expand All @@ -35,6 +38,14 @@ module.exports = (robot) ->
params.loc = s.slice(4)
console.log 'loc: ' + params.loc

if params.loc && !params.loc.match(/$/)
params.loc += ''

if params.kw && !categories[params.kw]?
return msg.reply('Category ' + params.kw + ' does not exist. See http://tabelog.com/cat_lst/')
if params.loc && !areas[params.loc]?
return msg.reply('Area ' + params.loc + ' does not exist.')

unless params.type
d = new Date()
h = d.getHours()
Expand All @@ -55,41 +66,55 @@ module.exports = (robot) ->
messages = []
messages.push restaurant.name
if restaurant.stars? and restaurant.stars != '' and restaurant.score? and restaurant.score != ''
messages.push restaurant.stars + ' ' + restaurant.score
messages.push restaurant.stars + ' ' + formatScore(restaurant.score)
messages.push restaurant.link
message = messages.join("\n")
msg.send restaurant.image, message

endpoint = 'http://tabelog.com/rst/rstsearch'
endpoint = 'http://tabelog.com/'

findRestaurants = (params, callback) ->
# construct URL like this: http://tabelog.com/tokyo/A1304/A130401/R7443/rstLst/YC99/?RdoCosTp=2
url = new String(endpoint)
qs = []
if params.type == 'lunch'
qs.push 'SrtT=rtl'
qs.push 'RdoCosTp=1'
else if params.type == 'dinner'
qs.push 'SrtT=rtd'
else
qs.push 'SrtT=rt'
if params.kw
qs.push 'sk=' + encodeURIComponent params.kw
qs.push 'RdoCosTp=2'
if params.loc
qs.push 'sa=' + encodeURIComponent params.loc
area = areas[params.loc]
url += area.city + '/' + area.code1 + '/' + area.code2 + '/' + area.code3 + '/'
url += 'rstLst/'
if params.kw
category = categories[params.kw]
url += category.code + '/'

url = endpoint + '?' + qs.join('&')
url = url + '?' + qs.join('&')
console.log "url: " + url
request url, (error, response, body) ->
if !error and response.statusCode is 200
$ = cheerio.load body
restaurants = $('.rstlst-group').map (idx, elem)->
restaurants = $('.list-rst').map (idx, elem)->
$restaurant = $(this)
return {
name: $restaurant.find('.mname a').text(),
link: $restaurant.find('.mname a').attr('href'),
image: $restaurant.find('.photoimg img').attr('src'),
score: $restaurant.find('.score-overall .score').text(),
stars: $restaurant.find('.score-overall .star').text(),
name: $restaurant.find('.list-rst__rst-name a').text(),
link: $restaurant.find('.list-rst__rst-name a').attr('href'),
image: $restaurant.find('.cpy-main-image').attr('data-original'),
score: $restaurant.find('.list-rst__rating-val').text(),
stars: $restaurant.find('.cpy-review-count').text(),
}
callback restaurants
else
console.log error

formatScore = (str) ->
score = ''
f = parseFloat(str)
i = Math.round(f)
for j in [1..5]
if i >= j
score += ''
else
score += ''
return score

16 changes: 5 additions & 11 deletions test/tabelog_test.coffee
Expand Up @@ -21,10 +21,6 @@ describe 'tabelog', ->
robot.adapter.on "connected", ->
robot.loadFile path.resolve('.', 'src', 'scripts'), 'tabelog.coffee'

# load help scripts to test help messages
hubotScripts = path.resolve 'node_modules', 'hubot', 'src', 'scripts'
robot.loadFile hubotScripts, 'help.coffee'

user = robot.brain.userForId '1', {
name: 'dtaniwaki'
room: '#mocha'
Expand All @@ -47,8 +43,6 @@ describe 'tabelog', ->
it 'has help messages', ->
commands = robot.helpCommands()
expect(commands).to.eql [
"hubot help - Displays all of the help commands that Hubot knows about.",
"hubot help <query> - Displays all help commands that match <query>.",
"hubot tabelog (<lunch|dinner>) for <keyword> in <area> - pick up a restaurant with the keyword in the area"
]

Expand All @@ -57,7 +51,7 @@ describe 'tabelog', ->
adapter.on "send", (envelope, strings)->
try
expect(strings).to.have.length(2)
expect(strings[0]).to.match /^http:\/\/.*\.jpg/
expect(strings[0]).to.match /^https:\/\/.*\.jpg/
expect(strings[1]).to.match /tabelog.com/
do done
catch e
Expand All @@ -68,7 +62,7 @@ describe 'tabelog', ->
adapter.on "send", (envelope, strings)->
try
expect(strings).to.have.length(2)
expect(strings[0]).to.match /^http:\/\/.*\.jpg/
expect(strings[0]).to.match /^https:\/\/.*\.jpg/
expect(strings[1]).to.match /tabelog.com/
do done
catch e
Expand All @@ -79,7 +73,7 @@ describe 'tabelog', ->
adapter.on "send", (envelope, strings)->
try
expect(strings).to.have.length(2)
expect(strings[0]).to.match /^http:\/\/.*\.jpg/
expect(strings[0]).to.match /^https:\/\/.*\.jpg/
expect(strings[1]).to.match /tabelog.com/
do done
catch e
Expand All @@ -90,7 +84,7 @@ describe 'tabelog', ->
adapter.on "send", (envelope, strings)->
try
expect(strings).to.have.length(2)
expect(strings[0]).to.match /^http:\/\/.*\.jpg/
expect(strings[0]).to.match /^https:\/\/.*\.jpg/
expect(strings[1]).to.match /tabelog.com/
do done
catch e
Expand All @@ -101,7 +95,7 @@ describe 'tabelog', ->
adapter.on "send", (envelope, strings)->
try
expect(strings).to.have.length(2)
expect(strings[0]).to.match /^http:\/\/.*\.jpg/
expect(strings[0]).to.match /^https:\/\/.*\.jpg/
expect(strings[1]).to.match /tabelog.com/
do done
catch e
Expand Down

0 comments on commit 72a0f20

Please sign in to comment.