Posted By

rchk on 05/15/08


Tagged

jason ruby chat facebook comet


Versions (?)

Who likes this?

6 people have marked this snippet as a favorite

rchk
mmccrack
skammer
webstic
davidsi
kzelda


facebook chat


 / Published in: Ruby
 

URL: http://coderrr.wordpress.com/2008/05/06/facebook-chat-api/

requires mechanize and json gems.

  1. require 'mechanize'
  2. require 'json'
  3. require 'ostruct'
  4. require 'pp'
  5.  
  6. class FacebookChat
  7. def initialize(email, pass); @email, @pass = email, pass; end
  8.  
  9. def login
  10. @agent = WWW::Mechanize.new
  11. @agent.user_agent_alias = 'Windows IE 7'
  12. f = @agent.get("http://facebook.com/login.php").forms.first
  13. f.fields.name("email").value = @email
  14. f.fields.name("pass").value = @pass
  15. f.submit
  16. body = @agent.get("http://www.facebook.com/home.php").body
  17.  
  18. # parse info out of facebook home page
  19. @uid = %r{<a href=".+?/profile.php\?id=(\d+)" class="profile_nav_link">Profile</a>}.match(body)[1].to_i
  20. @channel = %r{"channel(\d+)"}.match(body)[1]
  21. @post_form_id = %r{<input type="hidden" id="post_form_id" name="post_form_id" value="([^"]+)}.match(body)[1]
  22. end
  23.  
  24. def wait_for_messages
  25. determine_initial_seq_number unless @seq
  26.  
  27. begin
  28. json = parse_json @agent.get(get_message_url(@seq)).body
  29. end while json["t"] == "continue" # no messages yet, keep waiting
  30. @seq += 1
  31.  
  32. json["ms"].select{|m| m['type'] == 'msg'}.map do |msg|
  33. info = msg.delete 'msg'
  34. msg['text'] = info['text']
  35. msg['time'] = Time.at(info['time']/1000)
  36. OpenStruct.new msg
  37. end.reject {|msg| msg.from == @uid } # get rid of messages from us
  38. end
  39.  
  40. def send_message(uid, text)
  41. r = @agent.post "http://www.facebook.com/ajax/chat/send.php",
  42. :msg_text => text,
  43. :msg_id => rand(999999999),
  44. :client_time => (Time.now.to_f*1000).to_i,
  45. :to => uid,
  46. :post_form_id => @post_form_id
  47. end
  48.  
  49. def buddy_list
  50. json = parse_json(@agent.post("http://www.facebook.com/ajax/presence/update.php",
  51. :buddy_list => 1, :post_form_id => @post_form_id, :user => @uid).body)
  52. json['payload']['buddy_list']['userInfos'].inject({}) do |hash, (uid, info)|
  53. hash.merge uid => info['name']
  54. end
  55. end
  56.  
  57. private
  58.  
  59. def determine_initial_seq_number
  60. # -1 will always be a bad seq number so fb will tell us what the correct one is
  61. json = parse_json @agent.get(get_message_url(-1)).body
  62. @seq = json["seq"].to_i
  63. end
  64.  
  65. def get_message_url(seq)
  66. "http://0.channel#{@channel}.facebook.com/x/0/false/p_#{@uid}=#{seq}"
  67. end
  68.  
  69. # get rid of initial js junk, like 'for(;;);'
  70. def parse_json(s)
  71. JSON.parse s.sub(/^[^{]+/, '')
  72. end
  73. end
  74.  
  75. if __FILE__ == $0
  76. fb = FacebookChat.new(ARGV.shift, ARGV.shift)
  77. fb.login
  78.  
  79. puts "Buddy List:"
  80. pp fb.buddy_list
  81.  
  82. Thread.abort_on_exception = true
  83. Thread.new do
  84. puts usage = "Enter message as <facebook_id> <message> (eg: 124423 hey man wassup?) or type 'buddy' for buddy list"
  85. loop do
  86. case gets.strip
  87. when 'buddy' then pp fb.buddy_list
  88. when /^(\d+) (.+)$/
  89. uid, text = $1.to_i, $2
  90. fb.send_message(uid, text)
  91. else
  92. puts usage
  93. end
  94. end
  95. end
  96.  
  97. # message receiving loop
  98. loop do
  99. fb.wait_for_messages.each do |msg|
  100. puts "[#{msg.time.strftime('%H:%M')}] #{msg.from_name} (#{msg.from}): #{msg.text}"
  101. end
  102. end
  103. end

Report this snippet  

You need to login to post a comment.