lib/hipbot/adapters/hipchat/connection.rb in hipbot-0.0.5 vs lib/hipbot/adapters/hipchat/connection.rb in hipbot-0.1.0

- old
+ new

@@ -1,123 +1,156 @@ module Hipbot module Adapters module Hipchat class Connection def initialize bot - initialize_bot(bot) - initialize_jabber - initialize_rooms - join_rooms + @bot = bot + @bot.connection = self + + return unless setup_bot setup_timers end - def reply room, message - send_message(room, message) + def restart! + exit_all_rooms # TODO: Nice quit + setup_bot end - def restart! - leave_rooms - initialize_jabber + def send_to_room(room, message) + @client.send_message(:groupchat, room.id, message) + end + + def send_to_user(user, message) + @client.send_message(:chat, user.id, message) + end + + def set_topic(room, topic) + @client.send_message(:groupchat, room.id, nil, topic) + end + + def set_presence(status = nil, type = :available) + @client.set_presence(type, nil, status) + end + + private + + def setup_bot + return unless initialize_client initialize_rooms + initialize_users + initialize_callbacks join_rooms + set_presence('Hello humans!') + true end - private + def initialize_client + ::Jabber.debug = true + @client = ::Jabber::MUC::HipchatClient.new(@bot.jid + '/' + @bot.name) + @client.connect(@bot.password) + end def initialize_rooms - @muc_browser = Jabber::MUC::MUCBrowser.new(@jabber) - @rooms = @muc_browser.muc_rooms('conf.hipchat.com').map { |jid, name| - ::Hipbot::Room.new(jid, name) - } + Room.bot = @bot + @client.get_rooms.each do |r| + Room.create(r[:item].jid, r[:item].iname, topic: r[:details]['topic']) + end + true end - def initialize_bot bot - @bot = bot - @bot.connection = self + def initialize_users + User.bot = @bot + @client.get_users.each do |v| + params = { + email: v[:vcard]['EMAIL/USERID'], + mention: v[:item].attributes['mention_name'], + title: v[:vcard]['TITLE'], + photo: v[:vcard]['PHOTO'], + } + User.create(v[:item].jid, v[:item].iname, params) + end + true end - def initialize_jabber - @jabber ||= ::Jabber::Client.new(@bot.jid) - @jabber.connect - @jabber.auth(@bot.password) - @jabber.send(::Jabber::Presence.new.set_type(:available)) + def join_rooms + if Room.empty? + Jabber::debuglog "No rooms to join" + return false + end + Room.each do |room_jid, _| + @client.join(room_jid) + end + true end - def join_rooms - rooms.each do |room| - puts "Joining #{room.name}" + def exit_all_rooms + Room.each do |room_jid, _| + @client.exit(room_jid, 'bye bye!') + end + end - # TODO rewrite (Simple)MUCClient to handle many rooms from one object - # as there is no need to create distinct objects and callback for each - # room since all of them have to process same data from @jabber stream. - # We probably should be able to do something like this: - # @jabber.set_presence([room1, room2], :available) - # @jabber.on_event do |time, jid, message| # JID includes sender and room/chat - # @jabber.send(jid, message) - room.connection = ::Jabber::MUC::SimpleMUCClient.new(@jabber) - room.connection.on_message do |time, sender, message| - puts "#{room.name} > #{time} <#{sender}> #{message}" - begin - @bot.tell(sender, room, message) - rescue => e - puts e.inspect - e.backtrace.each do |line| - puts line - end + def initialize_callbacks + @client.on_message do |room_jid, user_name, message| + room = Room[room_jid] + user = User[user_name] + next if room.nil? && user.nil? + room.params.topic = message.subject if message.subject.present? + next if user_name == @bot.name || message.body.blank? + Jabber::debuglog "[#{Time.now}] <#{room.name}> #{user_name}: #{message.body}" + begin + @bot.react(user, room, message.body) + rescue => e + Jabber::debuglog e.inspect + e.backtrace.each do |line| + Jabber::debuglog line end end + end - # TODO Get and store all user data from HipChat API - room.users = [] - room.connection.on_join do |time, nick| - room.users << nick + @client.on_private_message do |user_jid, message| + user = User[user_jid] + next if user.blank? || user.name == @bot.name + if message.body.nil? + # if message.active? + # elsif message.inactive? + # elsif message.composing? + # elsif message.gone? + # elsif message.paused? + # end + else + @bot.react(user, nil, message.body) end - room.connection.on_leave do |time, nick| - room.users.delete(nick) - end - room.connection.join("#{room.jid}/#{@bot.name}", nil, :history => false) end - # TODO handle sending private messages with 'reply'. - # Simplest way is to add room object for each private chat with param - # to distinguish whether to use conf or chat domain - # rooms.first.connection.on_private_message do |time, jid, message| - # send_message rooms.first, 'hello!', jid + @client.on_invite do |room_jid, user_name, room_name, topic| + Room.create(room_jid, room_name, topic: topic) + @client.join(room_jid) + end - ## Alternative sending: - # msg = ::Jabber::Message.new(jid, 'hello!') - # msg.type = :chat - # @jabber.send(msg) + @client.on_presence do |room_jid, user_name, pres| + room = Room[room_jid] + next if room.blank? || user_name.blank? + user = User[user_name] + if pres == 'unavailable' + if user_name == @bot.name + room.delete + elsif user.present? + room.user_ids.delete(user.id) + end + elsif pres.blank? && user.present? && room.user_ids.exclude?(user.id) + room.user_ids << user.id + end + end - ## We can trigger normal message callback but 'reply' won't work since hipchat PM uses - ## different jid (user_room@chat.hipchat.com/client_name) - # rooms.first.connection.message_block.call(time, sender, message) - # end + @client.activate_callbacks end - def leave_rooms - rooms.each do |room| - puts "Leaving #{room.name}" - room.connection.exit - end - end - def setup_timers - ::EM::add_periodic_timer(10) { - if !@jabber.nil? && @jabber.is_disconnected? - initialize_jabber - join_rooms - end + ::EM::add_periodic_timer(60) { + @client.keep_alive(@bot.password) if @client.present? } end - def send_message room, message, jid = nil - room.connection.say(message, jid) - end - - def rooms - @rooms || [] - end end end end end