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

トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2017-11-06 (月) 01:22:22 (710d)