rfetion 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/rfetion/buddy_list.rb +14 -0
- data/lib/rfetion/contact.rb +22 -8
- data/lib/rfetion/fetion.rb +101 -91
- data/lib/rfetion/message.rb +11 -0
- data/lib/rfetion/sipc_message.rb +31 -24
- data/lib/rfetion.rb +2 -0
- data/rfetion.gemspec +4 -2
- data/spec/rfetion/fetion_spec.rb +158 -3
- data/spec/spec.opts +1 -0
- metadata +4 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.2
|
data/lib/rfetion/contact.rb
CHANGED
@@ -1,11 +1,25 @@
|
|
1
|
-
class
|
2
|
-
|
1
|
+
class Fetion
|
2
|
+
class Contact
|
3
|
+
attr_accessor :id, :sid, :uri, :mobile_no, :nickname, :impresa, :nickname, :status
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
data/lib/rfetion/fetion.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
360
|
-
|
313
|
+
def pulse(expected=SipcMessage::OK)
|
314
|
+
curl_exec(SIPP, next_url, expected)
|
361
315
|
end
|
362
316
|
|
363
|
-
def
|
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
|
data/lib/rfetion/sipc_message.rb
CHANGED
@@ -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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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, :
|
75
|
+
attr_reader :code, :description
|
86
76
|
|
87
|
-
def initialize(code,
|
77
|
+
def initialize(code, description)
|
88
78
|
@code = code
|
89
|
-
@
|
79
|
+
@description = description
|
90
80
|
end
|
91
81
|
|
92
82
|
def to_s
|
93
|
-
"#@code #@
|
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.
|
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-
|
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",
|
data/spec/rfetion/fetion_spec.rb
CHANGED
@@ -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::
|
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
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.
|
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-
|
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
|