Skip to content

Instantly share code, notes, and snippets.

@naoto
Forked from tomohiro/mixi_voice_bot.rb
Created October 28, 2009 12:20
Show Gist options
  • Save naoto/220448 to your computer and use it in GitHub Desktop.
Save naoto/220448 to your computer and use it in GitHub Desktop.
mixi voice irc gateway
#!/usr/bin/env ruby
$LOAD_PATH << 'lib'
$LOAD_PATH << '../lib'
require 'optparse'
require 'rubygems'
require 'net/irc'
require 'uri'
require 'mechanize'
require 'nokogiri'
@options = {}
ARGV.options do |o|
o.on('-h VAL'){|v| @options[:host] = v }
o.on('-p VAL'){|v| @options[:port] = v }
o.on('-U VAL'){|v| @options[:user] = v }
o.on('-P VAL'){|v| @options[:pass] = v }
o.on('-n VAL'){|v| @options[:name] = v }
o.on('-c VAL'){|v| @options[:channel] = v }
o.on('-o VAL'){|v| @options[:owner] = v}
o.parse!
end
class MixiVoiceBot < Net::IRC::Client
def initialize (options)
@options = options
@irc_host = @options[:host] || 'your_irc_host'
@irc_port = @options[:port] || '6667'
@channel = @options[:channel] || '#mixi'
@bot_name = @options[:name] || 'voice'
@nickname = @options[:owner] || 'voice'
super(@irc_host, @irc_port, {
:nick => @bot_name,
:user => @bot_name,
:real => @bot_name,
:channel => @channel,
})
@agent = WWW::Mechanize.new
if ENV['http_proxy']
proxy = URI.parse(ENV['http_proxy'])
@agent.set_proxy(proxy.host, proxy.port)
end
@email = @options[:user] || 'your_mixi_mail@example.com'
@password = @options[:pass] || 'your_mixi_password'
@caches = []
@identity = nil
end
def start
mixi_login
@identity = get_identity
@socket = TCPSocket.open(@host, @port)
@socket.gets
post(NICK, @opts.nick)
post(USER, @opts.user, '0', '*', @opts.real)
post(JOIN, @opts.channel)
post_thread = Thread.new do
while line = @socket.gets
message = Message.parse(line)
puts message
name = "on_#{(COMMANDS[message.command.upcase] || message.command).downcase}"
send(name, message) if respond_to? name
end
end
get_thread = Thread.new do
loop do
get_voice
sleep 300
end
end
post_thread.join
get_thread.join
rescue IOError => e
@log.error 'IOError' + e.to_s
ensure
finish
end
def on_privmsg(message)
if message.prefix =~ Regexp.new(@nickname)
case message[1]
when /^re ([0-9]+) (.+)/
reply_voice($1, $2)
when /^rm ([0-9]+)/
remove_voice($1)
else
post_voice(message[1])
end
get_voice
end
end
def mixi_login
@agent.get 'http://mixi.jp' do |login_page|
login_page.form 'login_form' do |form|
form.email = @email
form.password = @password
end.submit
end
end
def post_voice(voice)
@agent.get 'http://mixi.jp/recent_echo.pl' do |post_page|
post_page.form_with(:action => 'add_echo.pl') do |form|
form.body = voice
end.submit
end
end
def reply_voice(key, voice)
if @caches.has_key? key
member_id = @caches[key][:member_id]
post_time = @caches[key][:post_time]
@agent.get 'http://mixi.jp/recent_echo.pl' do |post_page|
post_page.form_with(:action => '/add_echo.pl') do |form|
form.body = voice
form.parent_member_id = member_id
form.parent_post_time = post_time
end.submit
end
else
post(NOTICE, @opts.channel, '指定された返信先が見つかりません')
end
end
def remove_voice(post_time)
@agent.post "http://mixi.jp/delete_echo.pl?post_time=#{post_time}&post_key=#{@identity}&redirect=recent_echo"
@caches = crawl_recent_voice
end
def get_voice
voices = crawl_recent_voice
voices.sort.each do |key, voice|
if @caches.empty? or !@caches.has_key? key
post(PRIVMSG, @opts.channel, "[#{voice[:nickname]}]#{voice[:reply]} #{voice[:comment]} (#{key})")
sleep 2
end
end
@caches = voices
end
def get_identity
recent_page = @agent.get 'http://mixi.jp/recent_echo.pl'
identity = (Nokogiri::HTML(recent_page.body)/'input#post_key').first['value']
end
def crawl_recent_voice
recent_page = @agent.get 'http://mixi.jp/recent_echo.pl'
voices = {}
(Nokogiri::HTML(recent_page.body)/'td.comment').each do |comment|
key = timestamp(comment)
voices[key] = build_voice(comment)
end
voices
end
def timestamp(comment)
comment.at('div.echo_post_time').text
end
def build_voice(comment)
{
:member_id => comment.at('div.echo_member_id').text,
:post_time => comment.at('div.echo_post_time').text,
:nickname => comment.at('div.echo_nickname').text,
:reply => ((' ' + comment.at('a').text) if comment.at('a').text =~ /^>/),
:comment => comment.at('div.echo_body').text
}
end
end
MixiVoiceBot.new(@options).start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment