rfetion 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.1
1
+ 0.5.2
@@ -0,0 +1,14 @@
1
+ class Fetion
2
+ class BuddyList
3
+ attr_reader :id, :name
4
+
5
+ def initialize(id, name)
6
+ @id = id
7
+ @name = name
8
+ end
9
+
10
+ def self.parse(buddy_list)
11
+ self.new(buddy_list['id'], buddy_list['name'])
12
+ end
13
+ end
14
+ end
@@ -1,11 +1,25 @@
1
- class Contact
2
- attr_reader :sid, :uri, :mobile_no, :nickname, :impresa, :nickname
1
+ class Fetion
2
+ class Contact
3
+ attr_accessor :id, :sid, :uri, :mobile_no, :nickname, :impresa, :nickname, :status
3
4
 
4
- def initialize(attrs)
5
- @sid = attrs["sid"]
6
- @uri = attrs["su"]
7
- @mobile_no = attrs["m"]
8
- @nickname = attrs["n"]
9
- @impresa = attrs["i"]
5
+ STATUS = {
6
+ "400" => "在线",
7
+ "300" => "离开",
8
+ "600" => "繁忙",
9
+ "0" => "脱机"
10
+ }
11
+
12
+ def self.parse(c)
13
+ contact = self.new
14
+ contact.id = c['id']
15
+ p = c.children.first
16
+ contact.sid = p["sid"]
17
+ contact.uri = p["su"]
18
+ contact.mobile_no = p["m"]
19
+ contact.nickname = p["n"]
20
+ contact.impresa = p["i"]
21
+ contact.status = p["b"]
22
+ contact
23
+ end
10
24
  end
11
25
  end
@@ -9,7 +9,7 @@ require 'logger'
9
9
 
10
10
  class Fetion
11
11
  attr_accessor :mobile_no, :sid, :password
12
- attr_reader :user_id, :uri, :contacts, :response, :nickname
12
+ attr_reader :user_id, :uri, :contacts, :buddy_lists, :response, :nickname, :receives
13
13
 
14
14
  FETION_URL = 'http://221.176.31.39/ht/sd.aspx'
15
15
  FETION_LOGIN_URL = 'https://uid.fetion.com.cn/ssiportal/SSIAppSignInV4.aspx?mobileno=%mobileno%sid=%sid%&domains=fetion.com.cn;m161.com.cn;www.ikuwa.cn&v4digest-type=1&v4digest=%digest%'
@@ -21,8 +21,10 @@ class Fetion
21
21
 
22
22
  def initialize
23
23
  @call = @alive = @seq = 0
24
+ @buddy_lists = []
24
25
  @buddies = []
25
26
  @contacts = []
27
+ @receives = []
26
28
  @logger = Logger.new(STDOUT)
27
29
  @logger.level = Logger::INFO
28
30
  @guid = Guid.new.to_s
@@ -178,8 +180,7 @@ class Fetion
178
180
 
179
181
  curl_exec(SIPP, next_url('i'))
180
182
  curl_exec(SipcMessage.register_first(self))
181
- response = pulse
182
- parse_nonce(response)
183
+ pulse(SipcMessage::Unauthoried)
183
184
 
184
185
  @logger.debug "fetion register first success"
185
186
  end
@@ -189,8 +190,7 @@ class Fetion
189
190
 
190
191
  body = %Q|<args><device machine-code="B04B5DA2F5F1B8D01A76C0EBC841414C" /><caps value="ff" /><events value="7f" /><user-info mobile-no="#{@mobile_no}" user-id="#{@user_id}"><personal version="0" attributes="v4default" /><custom-config version="0" /><contact-list version="0" buddy-attributes="v4default" /></user-info><credentials domains="fetion.com.cn;m161.com.cn;www.ikuwa.cn;games.fetion.com.cn" /><presence><basic value="400" desc="" /></presence></args>|
191
192
  curl_exec(SipcMessage.register_second(self))
192
- response = pulse
193
- parse_info(response)
193
+ pulse
194
194
 
195
195
  @logger.debug "fetion register second success"
196
196
  end
@@ -199,11 +199,8 @@ class Fetion
199
199
  @logger.info "fetion get contacts"
200
200
 
201
201
  curl_exec(SipcMessage.get_group_list(self))
202
-
203
- response = curl_exec(SipcMessage.presence(self))
204
- response = curl_exec(SipcMessage.get_group_topic(self))
205
- parse_contacts(response)
206
-
202
+ curl_exec(SipcMessage.presence(self))
203
+ curl_exec(SipcMessage.get_group_topic(self))
207
204
  curl_exec(SipcMessage.get_address_list(self))
208
205
  pulse
209
206
 
@@ -214,11 +211,7 @@ class Fetion
214
211
  @logger.info "fetion send cat msg to #{receiver}"
215
212
 
216
213
  curl_exec(SipcMessage.send_cat_msg(self, receiver, content))
217
- response = pulse
218
-
219
- raise FetionException.new("Fetion Error: Send cat msg error") unless Net::HTTPSuccess === response
220
- sipc_message = SipcMessage.sipc_response(response.body)
221
- raise Fetion::SendMsgException.new("Fetion Error: Send cat msg error with #{sipc_message}") unless SipcMessage::OK === sipc_message
214
+ pulse
222
215
 
223
216
  @logger.info "fetion send cat msg to #{receiver} success"
224
217
  end
@@ -227,11 +220,7 @@ class Fetion
227
220
  @logger.info "fetion send cat sms to #{receiver}"
228
221
 
229
222
  curl_exec(SipcMessage.send_cat_sms(self, receiver, content))
230
- response = pulse
231
-
232
- raise FetionException.new("Fetion Error: Send cat sms error") unless Net::HTTPSuccess === response
233
- sipc_message = SipcMessage.sipc_response(response.body)
234
- raise Fetion::SendSmsException.new("Fetion Error: Send cat sms error with #{sipc_message}") unless SipcMessage::Send === sipc_message
223
+ pulse(SipcMessage::Send)
235
224
 
236
225
  @logger.info "fetion send cat sms to #{receiver} success"
237
226
  end
@@ -246,11 +235,7 @@ class Fetion
246
235
  @logger.info "fetion schedule send sms to #{receivers.join(', ')}"
247
236
 
248
237
  curl_exec(SipcMessage.set_schedule_sms(self, receivers, content, time.strftime('%Y-%m-%d %H:%M:%S')))
249
- response = pulse
250
-
251
- raise FetionException.new("Fetion Error: Set schedule sms error") unless Net::HTTPSuccess === response
252
- sipc_message = SipcMessage.sipc_response(response.body)
253
- raise Fetion::SetScheduleSmsException.new("Fetion Error: Set schedule sms error with #{sipc_message}") unless SipcMessage::OK === sipc_message
238
+ pulse
254
239
 
255
240
  @logger.info "fetion schedule send sms to #{receivers.join(', ')} success"
256
241
  end
@@ -260,13 +245,10 @@ class Fetion
260
245
  # friend_sip
261
246
  def add_buddy(options)
262
247
  uri = options[:friend_mobile] ? "tel:#{options[:friend_mobile]}" : "sip:#{options[:friend_sip]}"
263
-
264
248
  @logger.info "fetion send request to add #{uri} as friend"
249
+
265
250
  curl_exec(SipcMessage.add_buddy(self, options))
266
- response = pulse
267
- raise FetionException.new("Fetion Error: Add buddy error") unless Net::HTTPSuccess === response
268
- sipc_message = SipcMessage.sipc_response(response.body)
269
- raise Fetion::AddBuddyException.new("Fetion Error: Add buddy error with #{sipc_message}") unless SipcMessage::OK === sipc_message
251
+ pulse
270
252
 
271
253
  @logger.info "fetion send request to add #{uri} as friend success"
272
254
  end
@@ -276,25 +258,28 @@ class Fetion
276
258
  # sip
277
259
  def get_contact_info(options)
278
260
  uri = options[:mobile_no] ? "tel:#{options[:mobile_no]}" : "sip:#{options[:sip]}"
279
-
280
261
  @logger.info "fetion get contact info of #{uri}"
262
+
281
263
  curl_exec(SipcMessage.get_contact_info(self, uri))
282
- response = pulse
283
-
284
- raise FetionException.new("Fetion Error: get contact info error") unless Net::HTTPSuccess === response
285
- sipc_response = SipcMessage.sipc_response(response.body)
286
- raise Fetion::NoUserException.new("Fetion Error: get contact info #{uri} with #{sipc_response}") unless SipcMessage::OK === sipc_response
264
+ pulse
287
265
 
288
266
  @logger.info "fetion get contact info of #{uri} success"
289
267
  end
290
268
 
269
+ def keep_alive
270
+ @logger.info "fetion keep alive"
271
+
272
+ pulse
273
+
274
+ @logger.info "fetion keep alive success"
275
+ end
276
+
291
277
  def logout
292
278
  @logger.info "fetion logout"
293
279
 
294
280
  curl_exec(SipcMessage.logout(self))
295
- response = pulse
281
+ pulse
296
282
 
297
- # raise FetionException.new("Fetion Error: Logout error") unless response.is_a? Net::HTTPSuccess
298
283
  @logger.info "fetion logout success"
299
284
  end
300
285
 
@@ -324,65 +309,16 @@ class Fetion
324
309
  @logger.debug "user_id: " + @user_id
325
310
  @logger.debug "sid: " + @sid
326
311
  end
327
-
328
- def parse_nonce(response)
329
- raise FetionException.new("Fetion Error: Register first error.") unless Net::HTTPSuccess === response
330
- sipc_response = SipcMessage.sipc_response(response.body)
331
- raise Fetion::RegisterException.new("Fetion Error: Register first should get unauthorized response with #{sipc_response}.") unless SipcMessage::Unauthoried === sipc_response
332
- raise Fetion::NoNonceException.new("Fetion Error: No nonce found") unless response.body =~ /nonce="(.*?)",key="(.*?)",signature="(.*?)"/
333
-
334
- @nonce = $1
335
- @key = $2
336
- @signature = $3
337
- @response = calc_response
338
-
339
- @logger.debug "nonce: #{@nonce}"
340
- @logger.debug "key: #{@key}"
341
- @logger.debug "signature: #{@signature}"
342
- @logger.debug "response: #{@response}"
343
- end
344
-
345
- def parse_info(response)
346
- raise Fetion::FetionException.new("Fetion Error: Register second error.") unless Net::HTTPSuccess === response
347
- sipc_response = SipcMessage.sipc_response(response.body)
348
- raise Fetion::RegisterException.new("Fetion Error: Register second error with #{sipc_response}.") unless SipcMessage::OK === sipc_response
349
-
350
- response.body.scan(%r{<results>.*?</results>}).each do |results|
351
- doc = Nokogiri::XML(results)
352
- personal = doc.root.xpath("/results/user-info/personal").first
353
- @nickname = personal['nickname']
354
- doc.root.xpath("/results//buddies/b").each do |buddy|
355
- @buddies << {:uri => buddy["u"]}
356
- end
357
- end
358
312
 
359
- @logger.debug "nickname: #@nickname"
360
- @logger.debug "buddies: #{@buddies.inspect}"
313
+ def pulse(expected=SipcMessage::OK)
314
+ curl_exec(SIPP, next_url, expected)
361
315
  end
362
316
 
363
- def parse_contacts(response)
364
- raise FetionException.new('Fetion Error: get contacts error.') unless Net::HTTPSuccess === response
365
- sipc_response = SipcMessage.sipc_response(response.body)
366
- raise Fetion::GetContactsException.new("Fetion Error: get contacts failed with #{sipc_response}.") unless Net::HTTPSuccess === response and SipcMessage::OK === sipc_response
367
-
368
- response.body.scan(%r{<events>.*?</events>}).each do |results|
369
- doc = Nokogiri::XML(results)
370
- doc.root.xpath("/events//c/p").each do |person|
371
- @contacts << Contact.new(person) if person['sid']
372
- end
373
- end
374
-
375
- @logger.debug "contacts: #{@contacts.inspect}"
376
- end
377
-
378
- def pulse
379
- curl_exec(SIPP)
380
- end
381
-
382
- def curl_exec(body='', url=next_url)
317
+ def curl_exec(body='', url=next_url, expected=SipcMessage::OK)
383
318
  @logger.debug "fetion curl exec"
384
319
  @logger.debug "url: #{url}"
385
320
  @logger.debug "body: #{body}"
321
+
386
322
  uri = URI.parse(url)
387
323
  http = Net::HTTP.new(uri.host, uri.port)
388
324
  headers = {'Content-Type' => 'application/oct-stream', 'Pragma' => "xz4BBcV#{@guid}", 'User-Agent' => USER_AGENT, 'Cookie' => "ssic=#{@ssic}", 'Content-Length' => body.length.to_s}
@@ -391,6 +327,71 @@ class Fetion
391
327
  @logger.debug "response: #{response.inspect}"
392
328
  @logger.debug "response body: #{response.body}"
393
329
  @logger.debug "fetion curl exec complete"
330
+
331
+ raise FetionException.new("request_url: #{url}, request_body: #{body}, response: #{response.code}, response_body: #{response.body}") unless Net::HTTPSuccess === response
332
+ sipc_response = SipcMessage.sipc_response(response.body, self)
333
+
334
+ if sipc_response
335
+ raise Fetion::SipcException.new(sipc_response, "request_url: #{url}, request_body: #{body}, sipc_response: #{sipc_response}") unless expected === sipc_response
336
+
337
+ if sipc_response.code == 401
338
+ # unauthorized, get nonce, key and signature
339
+ raise Fetion::NoNonceException.new("Fetion Error: No nonce found") unless response.body =~ /nonce="(.*?)",key="(.*?)",signature="(.*?)"/
340
+ @nonce = $1
341
+ @key = $2
342
+ @signature = $3
343
+ @response = calc_response
344
+
345
+ @logger.debug "nonce: #{@nonce}"
346
+ @logger.debug "key: #{@key}"
347
+ @logger.debug "signature: #{@signature}"
348
+ @logger.debug "response: #{@response}"
349
+ else
350
+ response.body.scan(%r{<results>.*?</results>}).each do |results|
351
+ doc = Nokogiri::XML(results)
352
+ doc.root.xpath("/results/user-info/personal").each do |personal_element|
353
+ @nickname = personal_element['nickname']
354
+ @logger.debug "nickname: #@nickname"
355
+ end
356
+ doc.root.xpath("/results/user-info/contact-list/buddy-lists/buddy-list").each do |buddy_list|
357
+ @buddy_lists << Fetion::BuddyList.parse(buddy_list)
358
+ @logger.debug "buddy_lists: #{@buddy_lists.inspect}"
359
+ end
360
+ doc.root.xpath("/results/user-info/contact-list/buddies/b").each do |buddy|
361
+ @buddies << {:uri => buddy["u"]}
362
+ @logger.debug "buddies: #{@buddies.inspect}"
363
+ end
364
+ end
365
+
366
+ response.body.scan(%r{<events>.*?</events>}).each do |events|
367
+ doc = Nokogiri::XML(events)
368
+ doc.root.xpath("/events/event[@type='PresenceChanged']/contacts/c").each do |c|
369
+ contact = contacts.find {|contact| contact.id == c['id']}
370
+ if contact
371
+ contact.status = c.children.first['b']
372
+ else
373
+ @contacts << Fetion::Contact.parse(c) unless c['id'] == @user_id
374
+ end
375
+ end
376
+ end
377
+
378
+ receive_messages = response.body.scan(%r{M #{@sid} SIP-C/4.0.*?BN}m)
379
+ receive_messages = response.body.scan(%r{M #{@sid} SIP-C/4.0.*?SIPP$}m) if receive_messages.empty?
380
+ receive_messages.each do |message_response|
381
+ message_header, message_content = message_response.split(/(\r)?\n(\r)?\n/)
382
+ sip = sent_at = length = nil
383
+ message_header.split(/(\r)?\n/).each do |line|
384
+ case line
385
+ when /^F: sip:(.+)/ then sip = $1
386
+ when /^D: (.+)/ then sent_at = Time.parse($1)
387
+ when /^L: (\d+)/ then length = $1.to_i
388
+ end
389
+ end
390
+ text = message_content.slice(0, length)
391
+ @receives << Fetion::Message.new(sip, sent_at, text)
392
+ end
393
+ end
394
+ end
394
395
  response
395
396
  end
396
397
 
@@ -438,3 +439,12 @@ class Fetion::SetScheduleSmsException < FetionException; end
438
439
  class Fetion::AddBuddyException < FetionException; end
439
440
  class Fetion::GetContactsException < FetionException; end
440
441
  class Fetion::NoUserException < FetionException; end
442
+ class Fetion::SipcException < FetionException
443
+ attr_reader :code, :description, :message
444
+
445
+ def initialize(sipc_response, message)
446
+ @code = sipc_response.code
447
+ @description = sipc_response.description
448
+ @message = message
449
+ end
450
+ end
@@ -0,0 +1,11 @@
1
+ class Fetion
2
+ class Message
3
+ attr_reader :sip, :sent_at, :text
4
+
5
+ def initialize(sip, sent_at, text)
6
+ @sip = sip
7
+ @sent_at = sent_at
8
+ @text = text
9
+ end
10
+ end
11
+ end
@@ -58,39 +58,29 @@ class SipcMessage
58
58
  sipc_create(:command => 'R', :F => fetion.sid, :I => 1, :Q => '3 R', :X => 0, :with_l => false)
59
59
  end
60
60
 
61
- # command one of 'R', 'S'
62
- # with_l display L or not
63
- # body sipc body
64
- def self.sipc_create(options)
65
- options = {:body => '', :with_l => true}.merge(options)
66
- body = options.delete(:body)
67
- with_l = options.delete(:with_l)
68
-
69
- sorted_key = [:F, :I, :Q, :CN, :CL, :A, :AK, :X, :T, :K, :N, :SV]
70
- sipc = "#{options.delete(:command)} fetion.com.cn SIP-C/4.0\r\n"
71
- sorted_key.each {|k| sipc += "#{k}: #{options[k]}\r\n" if options[k]}
72
- sipc += "L: #{body == '' ? 4 : body.size}\r\n" if with_l
73
- sipc += "\r\n#{body}#{Fetion::SIPP}"
74
- sipc
75
- end
76
-
77
- def self.sipc_response(http_response_body)
78
- sipc, code, message = http_response_body.split(/(\r)?\n/).first.split(' ')
79
- RESPONSES[code.to_i].new(code, message)
61
+ def self.sipc_response(http_response_body, fetion)
62
+ return if http_response_body == Fetion::SIPP
63
+
64
+ if http_response_body =~ %r{^SIP-C/4.0}
65
+ sipc, code, *message = http_response_body.split(/(\r)?\n/).first.split(' ')
66
+ RESPONSES[code.to_i].new(code.to_i, message.join(' '))
67
+ elsif http_response_body =~ %r{(BN|M) #{fetion.sid} SIP-C/4.0}
68
+ SipcMessage::OK.new(200, $1)
69
+ end
80
70
  rescue NoMethodError
81
- raise FetionException.new("Fetion error: No response to #{code} #{message}")
71
+ raise FetionException.new("Fetion error: No response to #{code} #{message.join(' ')}")
82
72
  end
83
73
 
84
74
  class Response
85
- attr_reader :code, :message
75
+ attr_reader :code, :description
86
76
 
87
- def initialize(code, message)
77
+ def initialize(code, description)
88
78
  @code = code
89
- @message = message
79
+ @description = description
90
80
  end
91
81
 
92
82
  def to_s
93
- "#@code #@message"
83
+ "#@code #@description"
94
84
  end
95
85
  end
96
86
 
@@ -109,4 +99,21 @@ class SipcMessage
109
99
  404 => SipcMessage::NotFound,
110
100
  421 => SipcMessage::ExtentionRequired
111
101
  }
102
+
103
+ private
104
+ # command one of 'R', 'S'
105
+ # with_l display L or not
106
+ # body sipc body
107
+ def self.sipc_create(options)
108
+ options = {:body => '', :with_l => true}.merge(options)
109
+ body = options.delete(:body)
110
+ with_l = options.delete(:with_l)
111
+
112
+ sorted_key = [:F, :I, :Q, :CN, :CL, :A, :AK, :X, :T, :K, :N, :SV]
113
+ sipc = "#{options.delete(:command)} fetion.com.cn SIP-C/4.0\r\n"
114
+ sorted_key.each {|k| sipc += "#{k}: #{options[k]}\r\n" if options[k]}
115
+ sipc += "L: #{body == '' ? 4 : body.size}\r\n" if with_l
116
+ sipc += "\r\n#{body}#{Fetion::SIPP}"
117
+ sipc
118
+ end
112
119
  end
data/lib/rfetion.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'rubygems'
2
+ require File.dirname(__FILE__) + '/rfetion/buddy_list'
2
3
  require File.dirname(__FILE__) + '/rfetion/contact'
4
+ require File.dirname(__FILE__) + '/rfetion/message'
3
5
  require File.dirname(__FILE__) + '/rfetion/sipc_message'
4
6
  require File.dirname(__FILE__) + '/rfetion/fetion'
data/rfetion.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rfetion}
8
- s.version = "0.5.1"
8
+ s.version = "0.5.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Richard Huang"]
12
- s.date = %q{2010-05-10}
12
+ s.date = %q{2010-05-15}
13
13
  s.description = %q{rfetion is a ruby gem for China Mobile fetion service that you can send SMS free.}
14
14
  s.email = %q{flyerhzm@gmail.com}
15
15
  s.executables = ["rfetion", "rfetion"]
@@ -22,9 +22,11 @@ Gem::Specification.new do |s|
22
22
  "VERSION",
23
23
  "bin/rfetion",
24
24
  "lib/rfetion.rb",
25
+ "lib/rfetion/buddy_list.rb",
25
26
  "lib/rfetion/command.rb",
26
27
  "lib/rfetion/contact.rb",
27
28
  "lib/rfetion/fetion.rb",
29
+ "lib/rfetion/message.rb",
28
30
  "lib/rfetion/sipc_message.rb",
29
31
  "rfetion.gemspec",
30
32
  "spec/rfetion/fetion_spec.rb",
@@ -124,6 +124,7 @@ EOF
124
124
  @fetion.register_second
125
125
 
126
126
  @fetion.nickname.should == "flyerhzm"
127
+ @fetion.buddy_lists.collect {|buddy_list| buddy_list.name}.should == ['我的好友', '好友', '同学']
127
128
  end
128
129
  end
129
130
  end
@@ -131,6 +132,8 @@ EOF
131
132
  describe "get contacts" do
132
133
  before :each do
133
134
  @fetion.instance_variable_set(:@seq, 5)
135
+ @fetion.instance_variable_set(:@sid, "730020377")
136
+ @fetion.instance_variable_set(:@user_id, "390937727")
134
137
  end
135
138
 
136
139
  it "should get all contacts" do
@@ -227,6 +230,112 @@ EOF
227
230
  @fetion.get_contacts
228
231
  @fetion.contacts.collect {|contact| contact.sid}.should == ["793401629", "737769829", "660250260", "926157269", "669700695", "760087520", "480867781", "572512981", "638993408"]
229
232
  end
233
+
234
+ it "should get received msg" do
235
+ FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=6", :body => "SIPP")
236
+ response_body =<<-EOF
237
+ SIP-C/4.0 200 OK
238
+ I: 3
239
+ Q: 1 S
240
+ L: 59
241
+
242
+ <results><group-list version ="1" ></group-list></results>SIPP
243
+ EOF
244
+ FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=7", :body => "SIPP")
245
+ response_body =<<-EOF
246
+ SIP-C/4.0 200 OK
247
+ I: 4
248
+ Q: 1 SUB
249
+
250
+ M 730020377 SIP-C/4.0
251
+ F: sip:480867781@fetion.com.cn;p=16105
252
+ I: -1
253
+ C: text/plain
254
+ Q: 2 M
255
+ D: Mon, 10 May 2010 14:26:17 GMT
256
+ L: 12
257
+
258
+ testtesttestBN 730020377 SIP-C/4.0
259
+ N: SystemNotifyV4
260
+ L: 84
261
+ I: 1
262
+ Q: 3 BN
263
+
264
+ <events><event type="MobileMailBoxChanged"><mail unread-count="1"/></event></events>BN 730020377 SIP-C/4.0
265
+ N: PresenceV4
266
+ I: 1
267
+ L: 322
268
+ Q: 4 BN
269
+
270
+ <events><event type="PresenceChanged"><contacts><c id="222516658"><p v="0" sid="793401629" su="sip:793401629@fetion.com.cn;p=1919" m="13601804916" c="CMCC" cs="0" s="1" l="0" svc="" n="Peter" i="人生哈哈哈" p="428986348" sms="0.0:0:0" sp="0" sh="0"/><pr di="" b="0" d="" dt="" dc="0"/></c></contacts></event></events>BN 730020377 SIP-C/4.0
271
+ N: PresenceV4
272
+ I: 1
273
+ L: 329
274
+ Q: 5 BN
275
+
276
+ <events><event type="PresenceChanged"><contacts><c id="229415466"><p v="0" sid="737769829" su="sip:737769829@fetion.com.cn;p=4078" m="13817731963" c="CMCC" cs="0" s="1" l="8" svc="" n="ice" i="" p="-2000590228" sms="0.0:0:0" sp="0" sh="0"/><pr di="PCCL030516427968" b="400" d="" dt="PC" dc="137"/></c></contacts></event></events>BN 730020377 SIP-C/4.0
277
+ N: PresenceV4
278
+ I: 1
279
+ L: 303
280
+ Q: 6 BN
281
+
282
+ <events><event type="PresenceChanged"><contacts><c id="228358286"><p v="0" sid="660250260" su="sip:660250260@fetion.com.cn;p=3854" m="13795359343" c="CMCC" cs="0" s="1" l="4" svc="" n="蔡智武" i="" p="0" sms="0.0:0:0" sp="0" sh="0"/><pr di="" b="0" d="" dt="" dc="0"/></c></contacts></event></events>BN 730020377 SIP-C/4.0
283
+ N: PresenceV4
284
+ I: 1
285
+ L: 643
286
+ Q: 7 BN
287
+
288
+ <events><event type="PresenceChanged"><contacts><c id="390937727"><p v="0" cs="0" n="flyerhzm" i="http://www.fetionrobot.com" sms="0.0:0:0" sp="0"/></c><c id="665046562"><p v="0" sid="926157269" su="sip:926157269@fetion.com.cn;p=12906" m="" c="CMCC" cs="0" s="1" l="0" svc="" n="黄雅莉" i="" p="0" sms="10099.12:57:24" sp="0" sh="0"/><pr di="" b="0" d="" dt="" dc="0"/></c><c id="227091544"><p v="0" sid="669700695" su="sip:669700695@fetion.com.cn;p=3546" m="13764589545" c="CMCC" cs="0" s="1" l="10" svc="" n="郭庆" i="looloo" p="598224859" sms="0.0:0:0" sp="0" sh="0"/><pr di="" b="0" d="" dt="" dc="0"/></c></contacts></event></events>BN 730020377 SIP-C/4.0
289
+ N: PresenceV4
290
+ I: 1
291
+ L: 338
292
+ Q: 8 BN
293
+
294
+ <events><event type="PresenceChanged"><contacts><c id="296436724"><p v="0" sid="760087520" su="sip:760087520@fetion.com.cn;p=2467" m="13656681075" c="CMCC" cs="0" s="1" l="5" svc="" n="蒋健" i="TD只需成功,不许失败" p="2074595345" sms="0.0:0:0" sp="0" sh="0"/><pr di="" b="0" d="" dt="" dc="0"/></c></contacts></event></events>BN 730020377 SIP-C/4.0
295
+ N: PresenceV4
296
+ I: 1
297
+ L: 291
298
+ Q: 9 BN
299
+
300
+ <events><event type="PresenceChanged"><contacts><c id="732743291"><p v="0" sid="480867781" su="sip:480867781@fetion.com.cn;p=16105" m="" c="" cs="1" s="1" l="0" svc="" n="黄志敏" i="" p="0" sms="365.0:0:0" sp="0" sh="1"/><pr di="" b="0" d="" dt="" dc="0"/></c></contacts></event></events>BN 730020377 SIP-C/4.0
301
+ N: PresenceV4
302
+ I: 1
303
+ L: 369
304
+ Q: 10 BN
305
+
306
+ <events><event type="PresenceChanged"><contacts><c id="226911221"><p v="0" sid="572512981" su="sip:572512981@fetion.com.cn;p=3544" m="13764325001" c="CMCC" cs="0" s="1" l="10" svc="" n="陈勇sh" i="http://slide.news.sina.com.cn/c/slide_1_797_11165.html#p=1" p="-98773891" sms="0.0:0:0" sp="0" sh="0"/><pr di="" b="0" d="" dt="" dc="0"/></c></contacts></event></events>BN 730020377 SIP-C/4.0
307
+ N: PresenceV4
308
+ I: 1
309
+ L: 300
310
+ Q: 11 BN
311
+
312
+ <events><event type="PresenceChanged"><contacts><c id="295098062"><p v="0" sid="638993408" su="sip:638993408@fetion.com.cn;p=2242" m="13634102006" c="CMCC" cs="0" s="1" l="0" svc="" n="梦妍" i="" p="0" sms="0.0:0:0" sp="0" sh="0"/><pr di="" b="0" d="" dt="" dc="0"/></c></contacts></event></events>SIPP
313
+ EOF
314
+ FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=8", :body => response_body)
315
+ response_body =<<-EOF
316
+ SIP-C/4.0 200 OK
317
+ I: 5
318
+ Q: 1 S
319
+ L: 835
320
+
321
+ <results><topic-list event="RecommendGroupTopic" version="171" max-count="5"><topic title="陌上人如玉 韩庚世无双" url="http://group.fetion.com.cn/topic/common/31333572/196313?c=[c:m161.com.cn]" create-date="2010-5-6 15:36:30" id="171" topic-type="1" /><topic title="世博园10大最美景观" url="http://group.fetion.com.cn/topic/common/8249155/196251?c=[c:m161.com.cn]" create-date="2010-5-6 15:33:49" id="170" topic-type="1" /><topic title="诺基亚价值百万的手机" url="http://group.fetion.com.cn/topic/common/7366464/196288?c=[c:m161.com.cn]" create-date="2010-5-6 15:31:57" id="169" topic-type="1" /><topic title="选秀调查:伪娘的真相" url="http://group.fetion.com.cn/topic/common/30660603/196323?c=[c:m161.com.cn]" create-date="2010-5-6 15:22:51" id="168" topic-type="1" /></topic-list></results>SIPP
322
+ EOF
323
+ FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=9", :body => response_body)
324
+ response_body =<<-EOF
325
+ SIP-C/4.0 200 OK
326
+ I: 6
327
+ Q: 1 S
328
+ L: 61
329
+
330
+ <results><contacts version="326661305" ></contacts></results>SIPP
331
+ EOF
332
+ FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=10", :body => response_body)
333
+ @fetion.get_contacts
334
+ @fetion.contacts.collect {|c| c.sid}.should == ["793401629", "737769829", "660250260", "926157269", "669700695", "760087520", "480867781", "572512981", "638993408"]
335
+ @fetion.receives.collect {|r| r.sip}.should == ["480867781@fetion.com.cn;p=16105"]
336
+ @fetion.receives.collect {|r| r.sent_at}.should == [Time.parse("Mon, 10 May 2010 14:26:17 GMT")]
337
+ @fetion.receives.collect {|r| r.text}.should == ["testtesttest"]
338
+ end
230
339
  end
231
340
 
232
341
  describe "send msg" do
@@ -353,7 +462,7 @@ Q: 1 S
353
462
  SIPP
354
463
  EOF
355
464
  FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=13", :body => response_body)
356
- lambda {@fetion.get_contact_info(:friend_mobile => '15800681505')}.should raise_exception(Fetion::NoUserException)
465
+ lambda {@fetion.get_contact_info(:friend_mobile => '15800681505')}.should raise_exception(Fetion::SipcException)
357
466
  end
358
467
  end
359
468
 
@@ -363,8 +472,54 @@ EOF
363
472
  end
364
473
 
365
474
  it "should logout" do
366
- FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=13", :body => '')
367
- FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=14", :body => '')
475
+ FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=13", :body => "SIPP")
476
+ FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=14", :body => "SIPP")
477
+ end
478
+ end
479
+
480
+ describe "keep-alive" do
481
+ before :each do
482
+ @fetion.instance_variable_set(:@seq, 10)
483
+ @fetion.instance_variable_set(:@sid, "730020377")
484
+ contact = Fetion::Contact.new
485
+ contact.id = '295098062'
486
+ @fetion.instance_variable_set(:@contacts, [contact])
487
+ end
488
+
489
+ it "should get presence with online" do
490
+ response_body =<<-EOF
491
+ BN 730020377 SIP-C/4.0
492
+ N: PresenceV4
493
+ I: 1
494
+ L: 154
495
+ Q: 11 BN
496
+
497
+ <events><event type="PresenceChanged"><contacts><c id="295098062"><pr di="PCCL030340538483" b="400" d="" dt="PC" dc="17"/></c></contacts></event></events>SIPP
498
+ EOF
499
+ FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=11", :body => response_body)
500
+ @fetion.keep_alive
501
+ @fetion.contacts.find {|contact| contact.id == '295098062'}.status.should == "400"
502
+ end
503
+
504
+ it "should get receive msg" do
505
+ response_body =<<-EOF
506
+ M 730020377 SIP-C/4.0
507
+ I: -17
508
+ Q: 4 M
509
+ F: sip:638993408@fetion.com.cn;p=2242
510
+ C: text/html-fragment
511
+ K: SaveHistory
512
+ L: 12
513
+ D: Tue, 11 May 2010 15:18:56 GMT
514
+ XI: 7eb8bc4e9df742b2aa557f9e85c8d8af
515
+
516
+ testtesttestSIPP
517
+ EOF
518
+ FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=11", :body => response_body)
519
+ @fetion.keep_alive
520
+ @fetion.receives.collect {|r| r.sip}.should == ["638993408@fetion.com.cn;p=2242"]
521
+ @fetion.receives.collect {|r| r.sent_at}.should == [Time.parse("Tue, 11 May 2010 15:18:56 GMT")]
522
+ @fetion.receives.collect {|r| r.text}.should == ["testtesttest"]
368
523
  end
369
524
  end
370
525
  end
data/spec/spec.opts CHANGED
@@ -4,5 +4,6 @@ specdoc
4
4
  --reverse
5
5
  --timeout
6
6
  20
7
+ --backtrace
7
8
  --loadby
8
9
  mtime
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rfetion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-05-10 00:00:00 -06:00
12
+ date: 2010-05-15 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -47,9 +47,11 @@ files:
47
47
  - VERSION
48
48
  - bin/rfetion
49
49
  - lib/rfetion.rb
50
+ - lib/rfetion/buddy_list.rb
50
51
  - lib/rfetion/command.rb
51
52
  - lib/rfetion/contact.rb
52
53
  - lib/rfetion/fetion.rb
54
+ - lib/rfetion/message.rb
53
55
  - lib/rfetion/sipc_message.rb
54
56
  - rfetion.gemspec
55
57
  - spec/rfetion/fetion_spec.rb