Last active
March 5, 2016 04:25
-
-
Save lapis-zero09/4b750992f46a9a2e174d to your computer and use it in GitHub Desktop.
一人暮らしの寂しさを紛らわす彼女(bot)を作った話 ref: http://qiita.com/lapis_zero09/items/cdde08576abbcbedad4d
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
$ ruby -v | |
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux] |
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
$ gem install twitter | |
$ gem install tweetstream | |
$ gem install docomoru |
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
$ mkdir bot | |
$ cd bot | |
$ touch twcon.rb |
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
$ irb | |
irb(main):001:0> require './twcon.rb' | |
=> true | |
irb(main):002:0> eve = Eve.new | |
=> ~省略~ | |
irb(main):003:0> eve.say("test", "") | |
=> #<Twitter::Tweet id=705644033196994561> | |
(↑こんな感じのが出たら成功) | |
irb(main):004:0> |
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
$ touch main.rb |
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
$ touch ~/bot/r-recipe.rb |
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
require './r-recipe.rb' | |
~省略~ | |
begin | |
eve.timeline.userstream{|status| | |
contents=status.text | |
next if(contents=~/^RT/) | |
id=status.user.screen_name | |
id='@' + id + ' ' | |
# reply_answer | |
if(contents=~/@lapis_ko/)&&(status.user.screen_name!='lapis_ko') | |
postmatch=$' | |
# 料理推薦 | |
if(contents=~/飯/) | |
food=RecommendRecipe.new | |
if(contents=~/:|:/) | |
eve.say(id+food.call("#{$'}"), status.id) | |
else | |
eve.say(id+"ご飯にする?\n"+food.call("なんでもいい")+"食べたいものがあれば「ご飯:食べたいもの」で指定してね!", status.id) | |
end | |
# 会話 | |
else | |
postmatch.gsub!(/\s|[ ]|\?|\?/, "") | |
# QandA | |
if(postmatch=~/誰|何処|だれ|どこ|何時|いつ|どうやって|どうして|何故|なぜ|どの|何|なに|どれ|は$/) | |
eve.say(id+eve.docomoru_create_knowledge(postmatch), status.id) | |
# 会話 | |
else | |
eve.say(id+eve.docomoru_create_dialogue(postmatch), status.id) | |
end | |
end | |
next | |
end | |
# メンション以外の名前に反応 | |
if(contents=~/eve|Eve|イヴ|イブ|いぶ/)&&(status.user.screen_name!='lapis_ko') | |
called_name=['なに?', '呼んだ?','どうしたの?'] | |
eve.say(id+called_name.sample, status.id) | |
next | |
end | |
# 料理推薦 | |
if(contents=~/飯|お腹すいた/)&&(status.user.screen_name!='lapis_ko') | |
food=RecommendRecipe.new | |
eve.say(id+"ご飯にする?\n"+food.call("なんでもいい")+"食べたいものがあれば「ご飯:食べたいもの」で指定してね!", status.id) | |
next | |
end | |
#zero09がつぶやいたらリプライ | |
~省略~ |
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
# coding: utf-8 | |
require 'open-uri' | |
require 'json' | |
require 'yaml' | |
#nattoかMeCabどっちでもいい | |
require 'natto' | |
# require 'MeCab' | |
class RecommendRecipe | |
keys=YAML.load_file('./config.yml') | |
RECIPE_CATEGORY_URL="https://app.rakuten.co.jp/services/api/Recipe/CategoryList/20121121?format=json&elements=categoryName%2CcategoryId%2CparentCategoryId&categoryType=medium&applicationId=#{keys['rakuten_api_id']}" | |
RECIPES_URL="https://app.rakuten.co.jp/services/api/Recipe/CategoryRanking/20121121?format=json&formatVersion=2&applicationId=#{keys['rakuten_api_id']}&categoryId=" | |
def call(food) | |
hearing(food) | |
end | |
private | |
def hearing(food) | |
results = recipe_categories | |
if(food=='なんでもいい') | |
recipe_category_id = results[results.keys.sample] | |
recipe = choose_recipe(recipe_category_id) | |
return "#{food}なら、#{recipe['recipeTitle']} とかはどう? #{recipe['recipeUrl']}"+' <Supported by RWS>' | |
else | |
recipe_category_id = results.fetch(food, nil) | |
if(recipe_category_id.nil?) | |
words=[] | |
#require 'MeCab'の場合 | |
# mc=MeCab::Tagger.new() | |
# n=mc.parseToNode(food) | |
# while(n) | |
# if(n.feature.split(',')[0]=="名詞") | |
# words.push(n.surface) | |
# elsif(words.size>0) | |
# food=words.join("") | |
# break | |
# end | |
# n=n.next | |
# end | |
#require 'natto'の場合 | |
nt=Natto::MeCab.new | |
nt.parse(food){|n| | |
if(n.feature.split(',')[0]=="名詞") | |
words.push(n.surface) | |
elsif(words.size>0) | |
food=words.join("") | |
break | |
end | |
} | |
recipe_category_id = results.fetch(food, nil) | |
if(recipe_category_id.nil?) | |
return "#{food}だとわからないからもうちょっと詳しく教えて(漢字⇆ひらがなにするといいかも)" | |
else | |
recipe = choose_recipe(recipe_category_id) | |
return "#{food}だと、#{recipe['recipeTitle']} とかはどう? #{recipe['recipeUrl']}"+' <Supported by RWS>' | |
end | |
else | |
recipe = choose_recipe(recipe_category_id) | |
return "#{food}だと、#{recipe['recipeTitle']} とかはどう? #{recipe['recipeUrl']}"+' <Supported by RWS>' | |
end | |
end | |
end | |
def recipe_categories | |
response=open(RECIPE_CATEGORY_URL).read | |
results=JSON.parse(response.force_encoding('UTF-8')) | |
return results["result"]["medium"].map{|result| [result['categoryName'], "#{result['parentCategoryId']}-#{result['categoryId']}"]}.to_h | |
end | |
def choose_recipe(recipe_category_id) | |
response=open("#{RECIPES_URL}#{recipe_category_id}").read | |
results=JSON.parse(response.force_encoding('UTF-8')) | |
return results['result'][Random.rand(1 .. results['result'].count-1)] | |
end | |
end |
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
# coding:utf-8 | |
require 'yaml' | |
require 'twitter' | |
require 'tweetstream' | |
require 'docomoru' | |
class Eve | |
# 外部から参照できるメンバ変数 | |
attr_accessor :client, :timeline | |
def initialize | |
keys=YAML.load_file('./config.yml') | |
# restAPI初期化 | |
@client=Twitter::REST::Client.new{|config| | |
config.consumer_key=keys["api_key"] | |
config.consumer_secret=keys["api_secret"] | |
config.access_token=keys["access_token"] | |
config.access_token_secret=keys["access_token_secret"] | |
} | |
# StreamAPI初期化 | |
TweetStream.configure{|config| | |
config.consumer_key=keys["api_key"] | |
config.consumer_secret=keys["api_secret"] | |
config.oauth_token=keys["access_token"] | |
config.oauth_token_secret=keys["access_token_secret"] | |
config.auth_method=:oauth | |
} | |
@timeline=TweetStream::Client.new | |
# docomoAPI初期化 | |
@docomoru=Docomoru::Client.new(api_key: keys["docomo_api_key"]) | |
end | |
# 引数を投稿するメソッド | |
def say(words, id) | |
@client.update(words, :in_reply_to_status_id => id) | |
end | |
# 会話を生成する(docomoru) | |
def docomoru_create_dialogue(str) | |
response=@docomoru.create_dialogue(str) | |
return response.body["utt"] | |
end | |
# QandA(docomoru) | |
def docomoru_create_knowledge(str) | |
response=@docomoru.create_knowledge(str) | |
if(response.body["code"]=="E020010") | |
return response.body["message"]["textForDisplay"] | |
else | |
if(response.body["answers"][0]["linkUrl"]==nil) | |
return response.body["message"]["textForDisplay"] | |
else | |
return response.body["message"]["textForDisplay"]+"<"+response.body["answers"][0]["linkUrl"]+">" | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment