Source Code †
version.rb †
RURIPECO_VERSION = '0.5.00'
login.rb †
# ----- login information
TWITTER_ID = 'ruripeco'
TWITTER_PASS = '@twitpass@'
DB_ODBC = 'DBI:ODBC:koruri'
DB_MYSQL = 'DBI:mysql:koruri:localhost'
DBLOGIN = '@yourid@'
DBPASS = '@yourpass'
talk_cron.rb †
#!/usr/bin/ruby
require 'rubygems'
require 'twitter'
require 'dbi'
require 'mecab_util.rb'
require 'version.rb'
require 'login.rb'
require 'reply_manager.rb'
require 'ruripeco.rb'
# ---------------------------------
# ----- post work
# ---------------------------------
system = false
if ARGV[0] =~ /\-info/ then
system = true
end
# --- open DB
db = DBI.connect(DB_MYSQL, DBLOGIN, DBPASS)
db.do('SET NAMES utf8')
# --- query
begin
tweet = RuripecoTalk.new(db)
connect = KoruriTwitter.new(TWITTER_ID, TWITTER_PASS)
if system == true then
talk = sprintf("[system] wakeup Ruripeco Ver %s", RURIPECO_VERSION)
else
talk = tweet.get
end
if talk != nil then
connect.post(talk)
# add db
sql = "INSERT INTO ruripeco_talk VALUES(NULL,?,?)"
db.do(sql, talk, Time.now.to_i)
end
rescue => e
puts e
puts "error terminate."
ensure
# --- end
db.disconnect
end
# -*- coding: utf-8 -*-
$KCODE = "u"
require 'MeCab'
# ---------------------------------------
# --- define
# ---------------------------------------
MECAB_OPTION = ''
# ---------------------------------------
# --- class
# ---------------------------------------
class MecabParse
def initialize(sentence)
@sentence = sentence
@cache = false
@mecab = MeCab::Tagger.new()
@node = @mecab.parse(sentence)
@chunk = []
@node.each do |w|
next if w =~ /^EOS/
@chunk << w
end
end
def size
@chunk.size
end
def get_node
@chunk
end
def get_word( index )
val = ''
if ((0<=index) && (index < @chunk.size)) then
body = @chunk[index].split
val = body[0]
end
val
end
def get_yomi( index )
val = ''
if ((0<=index) && (index < @chunk.size)) then
body = @chunk[index].split
data = body[1].split(',')
if data.size > 7 then
val = data[7]
else
# - kana
val = body[0]
end
end
val
end
def get_hinshi( index )
val = ''
if ((0<=index) && (index < @chunk.size)) then
body = @chunk[index].split
data = body[1].split(',')
val = data[0]
end
val
end
def get_noun
val = []
append = ''
append_yomi = ''
for i in 0...@chunk.size
hinshi = get_hinshi(i)
append << get_word(i)
append_yomi << get_yomi(i)
else
if !append.empty? then
val << append+' '+append_yomi
end
append = ''
append_yomi = ''
end
end
if !append.empty? then
val << append+' '+append_yomi
end
val
end
end
reply_manager.rb †
# ---------------------------------
# ----- reply manager
# ---------------------------------
class KoruriReplayManager
def initialize(koruridb, myuserid)
@mention_id = []
@db = koruridb
@myname = myuserid
from = '@'+myuserid
overcheck = Hash.new
sql = 'SELECT * FROM ruripeco_mention WHERE process=0 ORDER BY time ASC'
sth = @db.execute(sql)
sth.fetch do |row|
if (row[1] == myuserid) || (row[3] < (Time.now.to_i - 3600)) then
processed(row[0].to_i)
else
if overcheck.key?(row[1]) == false then
@mention_id << row[0].to_i
overcheck[row[1]] = 1
else
processed(row[0].to_i)
end
end
end
sth.finish
end
def size
@mention_id.size
end
def processed(id)
sql = 'UPDATE ruripeco_mention SET process=1 WHERE id=?'
@db.do(sql, id)
end
def noun_target(user, sentence)
noun = []
sentence.gsub!(/^\.@/, '@')
sentence.gsub!(/^@#{@myname}/, '')
token = MecabParse.new(sentence)
nounlist = token.get_noun
nounlist.each do |item|
next if item =~ /^http/
next if item =~ /^RT/
next if item =~ /^QT/
next if item =~ /^@[0-9a-zA-Z\-_]/
noun << item
puts item
end
noun[rand(noun.size)]
end
def parse_mention(id, result)
sql = 'SELECT * FROM ruripeco_mention WHERE id=?'
sth = @db.execute(sql, id)
sth.fetch do |row|
target = noun_target(row[1], row[2])
if target != '' then
result["user"] = row[1]
result["target"] = target.split.at(0)
end
end
sth.finish
processed(id)
end
def get
result = Hash.new
result["user"] = ''
result["target"] = ''
index = 0
for i in 0...@mention_id.size
if i < 5 then
parse_mention(@mention_id[i], result)
break if result != ''
else
processed(@mention_id[i])
end
end
result
end
end
url_shortener.rb †
$KCODE = "u"
require 'rubygems'
require 'net/http'
require 'uri'
#require 'json/pure'
class UrlShortener
def UrlShortener.get(url)
result = nil
Net::HTTP.version_1_2
Net::HTTP.start("ggl-shortener.appspot.com", 80) do |http|
response = http.get('/?url=' + URI.escape(url))
result = JSON.parse(response.body)
end
result["short_url"]
end
end
ruripeco.rb †
require 'url_shortener.rb'
# ---------------------------------
# ----- twitter class
# ---------------------------------
class KoruriTwitter
def initialize(id, pass)
httpauth = Twitter::HTTPAuth.new(TWITTER_ID, TWITTER_PASS)
@twit = Twitter::Base.new(httpauth)
end
def post(tweet)
@twit.update(tweet)
end
end
# ---------------------------------
# ----- random index class
# ---------------------------------
class RandomIndex
def initialize(size)
@ary_size = size
@ary = []
refresh
end
def refresh
for i in 0...@ary_size
@ary << i
end
for i in 0...@ary_size
t = @ary[i]
index = rand(@ary_size - i) + i
@ary[i] = @ary[index]
@ary[index] = i
end
end
def size
@ary_size
end
def get(index)
@ary[index]
end
end
# ---------------------------------
# ----- Ruripeco persona
# ---------------------------------
class RuripecoTalk
def initialize(db)
@db = db
@tempnum = 0
@nounnum = 0
sql = 'SELECT count(*) FROM noun_bank WHERE score>=1 AND appear>0'
sth = db.execute(sql)
sth.fetch do |row|
@nounnum = row[0].to_i
end
sth.finish
end
def get_template
talktemp = ""
num = 0
r = rand(@tempnum)
sql = sprintf("SELECT template_ruripeco.template_rank,template.nounnum FROM template,template_ruripeco WHERE template.id=template_ruripeco.id LIMIT %d,1", r)
sth = @db.execute(sql)
sth.fetch do |row|
talktemp = row[0]
num = row[1]
end
sth.finish
result = [talktemp, num]
end
# --- from all noun
def get_noun
noun = ""
r = rand(@nounnum)
sql = sprintf("SELECT word FROM noun_bank WHERE score>0 AND appear>0 LIMIT %d,1", r)
sth = @db.execute(sql)
sth.fetch do |row|
noun = row[0]
break
end
sth.finish
noun
end
def get_noun_link(prev, relay)
noun = ""
if prev == nil then
noun = get_noun
else
id = 0
sql = "SELECT noun_bank.id FROM noun_bank WHERE word=?"
sth = @db.execute(sql, prev)
sth.fetch do |row|
id = row[0].to_i
end
sth.finish
sql = "SELECT noun_bank.word FROM noun_bank,noun_link WHERE noun_link.nounid=? AND noun_bank.id=noun_link.link AND noun_bank.score>0 AND noun_bank.appear>0 AND noun_link.appear>2 AND noun_bank.word<>? ORDER BY noun_bank.appear DESC"
sth = @db.execute(sql, id, prev)
count = 0
linkword = []
sth.fetch do |row|
linkword << row[0]
count += 1
end
sth.finish
if count > 0 then
r = rand(count)
noun = linkword[r]
else
noun = get_noun
end
end
noun
end
# ----------------------------------
# get noun follower
# ----------------------------------
def get_noun_follow_list(noun)
word = ''
# - get noun id
id = 0
sql = "SELECT noun_bank.id FROM noun_bank WHERE word=?"
sth = @db.execute(sql, noun)
sth.fetch do |row|
id = row[0].to_i
end
sth.finish
# - get follow list
follow = []
sql = "SELECT noun_follow.word FROM noun_follow,noun_follow_link WHERE noun_follow_link.noun=? AND noun_follow_link.follow=noun_follow.id AND noun_follow.score>0"
sth = @db.execute(sql, id)
sth.fetch do |row|
follow << row[0]
end
sth.finish
follow
end
def get_noun_follow_word(noun)
list = get_noun_follow_list(noun)
num = list.size
if num > 0 then
word = list[rand(num)]
else
word = '?'
end
word
end
def get_noun_follow_backlist(noun)
word = ''
# - get noun id
id = 0
sql = "SELECT noun_bank.id FROM noun_bank WHERE word=?"
sth = @db.execute(sql, noun)
sth.fetch do |row|
id = row[0].to_i
end
sth.finish
# - get follow list
follow = []
sql = "SELECT noun_follow.word FROM noun_follow,noun_precede_link WHERE noun_precede_link.noun=? AND noun_precede_link.precede=noun_follow.id AND noun_follow.score>0"
sth = @db.execute(sql, id)
sth.fetch do |row|
follow << row[0]
end
sth.finish
follow
end
def get_noun_follow_backword(noun)
list = get_noun_follow_backlist(noun)
num = list.size
if num > 0 then
word = list[rand(num)]
else
word = '?'
end
word
end
def get_noun_follow_terminate(noun)
word = ''
list = get_noun_follow_list(noun)
num = list.size
index = RandomIndex.new(num)
if num > 0 then
for loop in 0...num
i = index.get(loop)
word = list[i]
end
word = list[i]
end
word = list[i]
end
word = list[i]
end
word = list[i]
end
break if word != ''
end
end
if word == '' then
end
word
end
# ----------------------------------
# full Markov chain
# ----------------------------------
def get_linking_noun_list(precede, prevnoun)
word = ''
# - get follow id
id1 = 0
id2 = 0
sql = "SELECT noun_follow.id FROM noun_follow WHERE word=?"
sth = @db.execute(sql, precede)
sth.fetch do |row|
id1 = row[0].to_i
break
end
sth.finish
sql = "SELECT noun_bank.id FROM noun_bank WHERE word=?"
sth = @db.execute(sql, prevnoun)
sth.fetch do |row|
id2 = row[0].to_i
break
end
sth.finish
# - get follow list
follow = []
sql = "SELECT noun_bank.word FROM noun_bank,noun_precede_link,noun_link WHERE noun_precede_link.precede=? AND noun_link.link=? AND noun_precede_link.noun=noun_bank.id AND noun_bank.id=noun_link.nounid AND noun_bank.score>0"
sth = @db.execute(sql, id1, id2)
sth.fetch do |row|
follow << row[0]
end
sth.finish
follow
end
def get_linking_precede_list(precede)
word = ''
# - get follow id
id = 0
sql = "SELECT noun_follow.id FROM noun_follow WHERE word=?"
sth = @db.execute(sql, precede)
sth.fetch do |row|
id = row[0].to_i
break
end
sth.finish
# - get follow list
follow = []
sql = "SELECT noun_bank.word FROM noun_bank,noun_precede_link WHERE noun_precede_link.precede=? AND noun_precede_link.noun=noun_bank.id AND noun_bank.score>0"
sth = @db.execute(sql, id)
sth.fetch do |row|
follow << row[0]
end
sth.finish
follow
end
def get_next_linking_noun(precede, prevnoun)
list = get_linking_noun_list(precede, prevnoun)
if list.size == 0 then
list = get_linking_precede_list(precede)
end
num = list.size
if num > 0 then
index = RandomIndex.new(num)
for i in 0...num
word = list[index.get(i)]
followlist = get_noun_follow_list(word)
break if followlist.size > 0
end
else
word = get_noun
end
word
end
# ----------------------------------
# reverse Markov chain
# ----------------------------------
def get_linking_noun_reverse_list(precede, nextnoun)
word = ''
# - get follow id
id1 = 0
id2 = 0
sql = "SELECT noun_follow.id FROM noun_follow WHERE word=?"
sth = @db.execute(sql, precede)
sth.fetch do |row|
id1 = row[0].to_i
break
end
sth.finish
sql = "SELECT noun_bank.id FROM noun_bank WHERE word=?"
sth = @db.execute(sql, nextnoun)
sth.fetch do |row|
id2 = row[0].to_i
break
end
sth.finish
# - get follow list
follow = []
sql = "SELECT noun_bank.word FROM noun_bank,noun_follow_link,noun_link WHERE noun_follow_link.follow=? AND noun_link.link=? AND noun_follow_link.noun=noun_bank.id AND noun_bank.id=noun_link.nounid AND noun_bank.appear>2 AND noun_bank.score>0"
sth = @db.execute(sql, id1, id2)
sth.fetch do |row|
follow << row[0]
end
sth.finish
follow
end
def get_linking_precede_reverse_list(precede)
word = ''
# - get follow id
id = 0
sql = "SELECT noun_follow.id FROM noun_follow WHERE word=?"
sth = @db.execute(sql, precede)
sth.fetch do |row|
id = row[0].to_i
break
end
sth.finish
# - get follow list
follow = []
sql = "SELECT noun_bank.word FROM noun_bank,noun_follow_link WHERE noun_follow_link.follow=? AND noun_follow_link.noun=noun_bank.id AND noun_bank.score>0"
sth = @db.execute(sql, id)
sth.fetch do |row|
follow << row[0]
end
sth.finish
follow
end
def get_back_linking_noun(precede, nextnoun)
list = []
list = get_linking_noun_reverse_list(precede, nextnoun)
if list.size == 0 then
list = get_linking_precede_reverse_list(precede)
end
num = list.size
if num > 0 then
index = RandomIndex.new(num)
for i in 0...num
word = list[index.get(i)]
followlist = get_noun_follow_backlist(word)
break if followlist.size > 0
end
else
word = get_noun
end
word
end
# ----------------------------------
# full chain compose
# ----------------------------------
def get_full_linking_sentence(target, nouns_num)
relay = target
talk = ''
chunk = []
prev_noun = ''
follow_cache = []
# -- target position
basepos = rand(nouns_num)
# -- to right
relay = target
prev_noun = relay
for loop_r in basepos...nouns_num
chunk[loop_r*2] = relay
prev_noun = relay
done = false
count = 0
while(done == false)
if loop_r < (nouns_num-1) then
relay2 = get_noun_follow_word(relay)
else
relay2 = get_noun_follow_terminate(relay)
end
if follow_cache.include?(relay2) == false then
relay = relay2
done = true
end
count += 1
break if count > 10
end
chunk[loop_r*2+1] = relay
follow_cache << relay
relay = get_next_linking_noun(relay, prev_noun)
end
# -- to left
relay = target
next_noun = target
for loop_l in 0...basepos
done = false
count = 0
while(done == false)
relay2 = get_noun_follow_backword(relay)
if follow_cache.include?(relay2) == false then
chunk[(basepos-loop_l-1)*2+1] = relay2
relay = relay2
done = true
end
count += 1
break if count > 10
end
follow_cache << relay
relay = get_back_linking_noun(relay, next_noun)
chunk[(basepos-loop_l-1)*2] = relay
next_noun = relay
end
# -- output
talk << chunk.join
talk
end
# ----------------------------------
# get target word
# ----------------------------------
def random_target_word(safe)
count = 0
while(count == 0)
id = 0
noun = get_noun
sql = "SELECT noun_bank.id FROM noun_bank WHERE word=?"
sth = @db.execute(sql, noun)
sth.fetch do |row|
id = row[0].to_i
end
sth.finish
sql = "SELECT noun_follow_link.follow FROM noun_bank,noun_follow_link WHERE noun_follow_link.noun=? AND noun_bank.id=noun_follow_link.noun AND noun_bank.score>0 AND noun_bank.appear>0 ORDER BY noun_bank.appear DESC"
sth = @db.execute(sql, id)
count = 0
linkword = []
sth.fetch do |row|
linkword << row[0]
count += 1
end
sth.finish
end
if (count < 2) && (safe < 10) then
noun = random_target_word(safe+1)
end
noun
end
def trend_word
noun = ''
trend_list = []
sql = "SELECT word FROM trend_word ORDER BY lastupdate DESC LIMIT 0,10"
sth = @db.execute(sql)
sth.fetch do |row|
trend_list << row[0]
end
sth.finish
offset = rand(10)
for i in 0...10
id = 0
score = 0
word = trend_list[(i+offset)%10]
sql = "SELECT noun_bank.id,noun_bank.score FROM noun_bank WHERE word=?"
sth = @db.execute(sql, word)
sth.fetch do |row|
id = row[0].to_i
score = row[1].to_i
end
sth.finish
if (id > 0) && (score > 0) then
noun = word
break
end
end
if noun == '' then
noun = random_target_word(0)
end
noun
end
def get_target_word
target = ''
if rand(100) < 50 then
target = random_target_word(0)
else
target = trend_word
end
target
end
# ----------------------------------
# ruripeco talk
# ----------------------------------
def build_sentence
talk = ''
targetword = get_target_word
nouns_num = rand(6) + 3
talk = get_full_linking_sentence(targetword, nouns_num)
end
def build_response_sentence(companion, targetword)
talk = ''
nouns_num = rand(6) + 3
talk = get_full_linking_sentence(targetword, nouns_num)
talk = sprintf("@%s %s", companion, talk)
end
def build_recommend_page_sentence
nowtime = Time.now.to_i
sql = "SELECT * FROM hot_url WHERE checktime>? LIMIT 0,60"
sth = @db.execute(sql, (nowtime - 2*60*60))
num = sth.fetch_all.size
sql = "SELECT * FROM hot_url WHERE checktime>? LIMIT 0,60"
sth = @db.execute(sql, (nowtime - 2*60*60))
target = rand(num)
count = 0
chunk = []
url = ''
sth.fetch do |row|
url = row[1]
chunk = row[2].to_s.split(' ')
break if count == target
count += 1
end
topic = chunk[rand(chunk.size)]
sth.finish
sql = "UPDATE hot_url SET process=1 WHERE url=?"
@db.do(sql, url)
#
talk = ''
nouns_num = rand(3) + 3
orgtalk = get_full_linking_sentence(topic, nouns_num)
talk = sprintf("%s %s", orgtalk, url)
if talk.size >135 then
talk = sprintf("%s %s", orgtalk, UrlShortener.get(url))
end
talk
end
def get
mention = KoruriReplayManager.new(@db, 'ruripeco')
#
timing = 0
sql = "SELECT * FROM property WHERE keyname='tweet_timing'"
sth = @db.execute(sql)
sth.fetch do |row|
timing = row[1].to_i
end
sth.finish
if timing == 0 then
if rand(10) > 7 then
talk = build_recommend_page_sentence
else
talk = build_sentence
end
timing = rand(7)+2
else
timing -= 1
if mention.size > 0 then
action = mention.get
talk = build_response_sentence(action['user'], action['target'])
end
end
sql = "UPDATE property SET value=? WHERE keyname='tweet_timing'"
@db.do(sql, timing)
#
talk
end
end