rfetion 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/rfetion/command.rb +1 -1
- data/lib/rfetion/fetion.rb +83 -68
- data/lib/rfetion/sipc_message.rb +14 -6
- data/rfetion.gemspec +2 -2
- data/spec/rfetion/fetion_spec.rb +1 -0
- data/spec/rfetion/sipc_message_spec.rb +4 -4
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.1
|
data/lib/rfetion/command.rb
CHANGED
@@ -86,7 +86,7 @@ begin
|
|
86
86
|
|
87
87
|
raise FetionException.new('You must input your mobile number or fetion sid, password and content') unless (options[:mobile_no] or options[:sid]) and options[:password] and options[:content]
|
88
88
|
if options[:time]
|
89
|
-
Fetion.
|
89
|
+
Fetion.set_schedule_sms(options)
|
90
90
|
else
|
91
91
|
Fetion.send_sms(options)
|
92
92
|
end
|
data/lib/rfetion/fetion.rb
CHANGED
@@ -20,9 +20,7 @@ class Fetion
|
|
20
20
|
DOMAIN = "fetion.com.cn"
|
21
21
|
|
22
22
|
def initialize
|
23
|
-
@call = 0
|
24
|
-
@alive = 0
|
25
|
-
@seq = 0
|
23
|
+
@call = @alive = @seq = 0
|
26
24
|
@buddies = []
|
27
25
|
@contacts = []
|
28
26
|
@logger = Logger.new(STDOUT)
|
@@ -146,6 +144,8 @@ class Fetion
|
|
146
144
|
end
|
147
145
|
|
148
146
|
def login
|
147
|
+
@logger.info "fetion login"
|
148
|
+
|
149
149
|
if @mobile_no
|
150
150
|
url = FETION_LOGIN_URL.sub('%mobileno%', @mobile_no).sub('sid=%sid%', '')
|
151
151
|
else
|
@@ -157,74 +157,82 @@ class Fetion
|
|
157
157
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
158
158
|
headers = {'User-Agent' => USER_AGENT}
|
159
159
|
response = http.request_get(uri.request_uri, headers)
|
160
|
+
parse_ssic(response)
|
160
161
|
|
161
|
-
|
162
|
-
|
163
|
-
parse_login_response(response)
|
162
|
+
@logger.info "fetion login success"
|
164
163
|
end
|
165
164
|
|
166
165
|
def register
|
166
|
+
@logger.info "fetion register"
|
167
|
+
|
167
168
|
call = next_call
|
168
169
|
register_first
|
169
170
|
register_second
|
170
171
|
call = next_call
|
172
|
+
|
173
|
+
@logger.info "fetion register success"
|
171
174
|
end
|
172
175
|
|
173
176
|
def register_first
|
177
|
+
@logger.debug "fetion register first"
|
178
|
+
|
174
179
|
curl_exec(SIPP, next_url('i'))
|
175
180
|
curl_exec(SipcMessage.register_first(self))
|
176
181
|
response = pulse
|
177
|
-
|
178
|
-
|
179
|
-
@nonce = $1
|
180
|
-
@key = $2
|
181
|
-
@signature = $3
|
182
|
-
@response = calc_response
|
182
|
+
parse_nonce(response)
|
183
183
|
|
184
|
-
@logger.debug "
|
185
|
-
@logger.debug "key: #{@key}"
|
186
|
-
@logger.debug "signature: #{@signature}"
|
187
|
-
@logger.debug "response: #{@response}"
|
184
|
+
@logger.debug "fetion register first success"
|
188
185
|
end
|
189
186
|
|
190
187
|
def register_second
|
188
|
+
@logger.debug "fetion register second"
|
189
|
+
|
191
190
|
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>|
|
192
191
|
curl_exec(SipcMessage.register_second(self))
|
193
192
|
response = pulse
|
193
|
+
parse_info(response)
|
194
194
|
|
195
|
-
|
196
|
-
|
197
|
-
parse_info(response.body)
|
198
|
-
parse_buddies(response.body)
|
195
|
+
@logger.debug "fetion register second success"
|
199
196
|
end
|
200
197
|
|
201
198
|
def get_contacts
|
199
|
+
@logger.info "fetion get contacts"
|
200
|
+
|
202
201
|
curl_exec(SipcMessage.get_group_list(self))
|
203
202
|
|
204
203
|
response = curl_exec(SipcMessage.presence(self))
|
205
204
|
response = curl_exec(SipcMessage.get_group_topic(self))
|
206
|
-
|
207
|
-
parse_contacts(response.body)
|
205
|
+
parse_contacts(response)
|
208
206
|
|
209
207
|
curl_exec(SipcMessage.get_address_list(self))
|
210
208
|
pulse
|
209
|
+
|
210
|
+
@logger.info "fetion get contacts success"
|
211
211
|
end
|
212
212
|
|
213
213
|
def send_msg(receiver, content)
|
214
|
-
@logger.info "fetion send msg to #{receiver}"
|
215
|
-
|
214
|
+
@logger.info "fetion send cat msg to #{receiver}"
|
215
|
+
|
216
|
+
curl_exec(SipcMessage.send_cat_msg(self, receiver, content))
|
216
217
|
response = pulse
|
217
218
|
|
218
|
-
raise
|
219
|
-
|
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
|
222
|
+
|
223
|
+
@logger.info "fetion send cat msg to #{receiver} success"
|
220
224
|
end
|
221
225
|
|
222
226
|
def send_sms(receiver, content)
|
223
227
|
@logger.info "fetion send cat sms to #{receiver}"
|
228
|
+
|
224
229
|
curl_exec(SipcMessage.send_cat_sms(self, receiver, content))
|
225
230
|
response = pulse
|
226
231
|
|
227
|
-
raise
|
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
|
235
|
+
|
228
236
|
@logger.info "fetion send cat sms to #{receiver} success"
|
229
237
|
end
|
230
238
|
|
@@ -240,7 +248,10 @@ class Fetion
|
|
240
248
|
curl_exec(SipcMessage.set_schedule_sms(self, receivers, content, time.strftime('%Y-%m-%d %H:%M:%S')))
|
241
249
|
response = pulse
|
242
250
|
|
243
|
-
raise
|
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
|
254
|
+
|
244
255
|
@logger.info "fetion schedule send sms to #{receivers.join(', ')} success"
|
245
256
|
end
|
246
257
|
|
@@ -253,7 +264,9 @@ class Fetion
|
|
253
264
|
@logger.info "fetion send request to add #{uri} as friend"
|
254
265
|
curl_exec(SipcMessage.add_buddy(self, options))
|
255
266
|
response = pulse
|
256
|
-
raise
|
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
|
257
270
|
|
258
271
|
@logger.info "fetion send request to add #{uri} as friend success"
|
259
272
|
end
|
@@ -265,23 +278,28 @@ class Fetion
|
|
265
278
|
uri = options[:mobile_no] ? "tel:#{options[:mobile_no]}" : "sip:#{options[:sip]}"
|
266
279
|
|
267
280
|
@logger.info "fetion get contact info of #{uri}"
|
268
|
-
curl_exec(SipcMessage.get_contact_info(self,
|
281
|
+
curl_exec(SipcMessage.get_contact_info(self, uri))
|
269
282
|
response = pulse
|
270
283
|
|
284
|
+
raise FetionException.new("Fetion Error: get contact info error") unless Net::HTTPSuccess === response
|
271
285
|
sipc_response = SipcMessage.sipc_response(response.body)
|
272
|
-
raise Fetion::NoUserException.new("Fetion Error: get contact info #{uri} with #{sipc_response
|
286
|
+
raise Fetion::NoUserException.new("Fetion Error: get contact info #{uri} with #{sipc_response}") unless SipcMessage::OK === sipc_response
|
273
287
|
|
274
288
|
@logger.info "fetion get contact info of #{uri} success"
|
275
289
|
end
|
276
290
|
|
277
291
|
def logout
|
292
|
+
@logger.info "fetion logout"
|
293
|
+
|
278
294
|
curl_exec(SipcMessage.logout(self))
|
279
295
|
response = pulse
|
280
296
|
|
281
297
|
# raise FetionException.new("Fetion Error: Logout error") unless response.is_a? Net::HTTPSuccess
|
298
|
+
@logger.info "fetion logout success"
|
282
299
|
end
|
283
300
|
|
284
|
-
def
|
301
|
+
def parse_ssic(response)
|
302
|
+
raise Fetion::LoginException.new('Fetion Error: Login failed.') unless Net::HTTPSuccess === response
|
285
303
|
raise Fetion::LoginException.new('Fetion Error: No ssic found in cookie.') unless response['set-cookie'] =~ /ssic=(.*);/
|
286
304
|
|
287
305
|
@ssic = $1
|
@@ -306,34 +324,54 @@ class Fetion
|
|
306
324
|
@logger.debug "user_id: " + @user_id
|
307
325
|
@logger.debug "sid: " + @sid
|
308
326
|
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
|
309
344
|
|
310
|
-
def parse_info(
|
311
|
-
|
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|
|
312
351
|
doc = Nokogiri::XML(results)
|
313
352
|
personal = doc.root.xpath("/results/user-info/personal").first
|
314
353
|
@nickname = personal['nickname']
|
315
|
-
end
|
316
|
-
|
317
|
-
@logger.debug "nickname: #@nickname"
|
318
|
-
end
|
319
|
-
|
320
|
-
def parse_buddies(response_body)
|
321
|
-
response_body.scan(%r{<results>.*?</results>}).each do |results|
|
322
|
-
doc = Nokogiri::XML(results)
|
323
354
|
doc.root.xpath("/results//buddies/b").each do |buddy|
|
324
355
|
@buddies << {:uri => buddy["u"]}
|
325
356
|
end
|
326
357
|
end
|
358
|
+
|
359
|
+
@logger.debug "nickname: #@nickname"
|
327
360
|
@logger.debug "buddies: #{@buddies.inspect}"
|
328
361
|
end
|
329
362
|
|
330
|
-
def parse_contacts(
|
331
|
-
|
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|
|
332
369
|
doc = Nokogiri::XML(results)
|
333
370
|
doc.root.xpath("/events//c/p").each do |person|
|
334
371
|
@contacts << Contact.new(person) if person['sid']
|
335
372
|
end
|
336
373
|
end
|
374
|
+
|
337
375
|
@logger.debug "contacts: #{@contacts.inspect}"
|
338
376
|
end
|
339
377
|
|
@@ -388,30 +426,6 @@ class Fetion
|
|
388
426
|
def self?(mobile_or_sid)
|
389
427
|
mobile_or_sid == @mobile_no or mobile_or_sid == @sid
|
390
428
|
end
|
391
|
-
|
392
|
-
[:login, :register, :get_contacts, :logout].each do |method|
|
393
|
-
class_eval <<-EOF
|
394
|
-
alias_method :origin_#{method}, :#{method}
|
395
|
-
|
396
|
-
def #{method}
|
397
|
-
@logger.info "fetion #{method.to_s.gsub(/_/, ' ')}"
|
398
|
-
origin_#{method}
|
399
|
-
@logger.info "fetion #{method.to_s.gsub(/_/, ' ')} success"
|
400
|
-
end
|
401
|
-
EOF
|
402
|
-
end
|
403
|
-
|
404
|
-
[:register_first, :register_second].each do |method|
|
405
|
-
class_eval <<-EOF
|
406
|
-
alias_method :origin_#{method}, :#{method}
|
407
|
-
|
408
|
-
def #{method}
|
409
|
-
@logger.debug "fetion #{method.to_s.gsub(/_/, ' ')}"
|
410
|
-
origin_#{method}
|
411
|
-
@logger.debug "fetion #{method.to_s.gsub(/_/, ' ')} success"
|
412
|
-
end
|
413
|
-
EOF
|
414
|
-
end
|
415
429
|
end
|
416
430
|
|
417
431
|
class FetionException < Exception; end
|
@@ -422,4 +436,5 @@ class Fetion::SendSmsException < FetionException; end
|
|
422
436
|
class Fetion::SendMsgException < FetionException; end
|
423
437
|
class Fetion::SetScheduleSmsException < FetionException; end
|
424
438
|
class Fetion::AddBuddyException < FetionException; end
|
439
|
+
class Fetion::GetContactsException < FetionException; end
|
425
440
|
class Fetion::NoUserException < FetionException; end
|
data/lib/rfetion/sipc_message.rb
CHANGED
@@ -34,8 +34,8 @@ class SipcMessage
|
|
34
34
|
sipc_create(:command => 'M', :F => fetion.sid, :I => fetion.next_call, :Q => '1 M', :T => receiver, :N => 'SendCatSMS', :body => content)
|
35
35
|
end
|
36
36
|
|
37
|
-
def self.
|
38
|
-
sipc_create(:command => 'M', :F => fetion.sid, :I => fetion.next_call, :Q => '
|
37
|
+
def self.send_cat_msg(fetion, receiver, content)
|
38
|
+
sipc_create(:command => 'M', :F => fetion.sid, :I => fetion.next_call, :Q => '2 M', :T => receiver, :K => 'SaveHistory', :N => 'CatMsg', :body => content)
|
39
39
|
end
|
40
40
|
|
41
41
|
def self.set_schedule_sms(fetion, receivers, content, time)
|
@@ -49,8 +49,8 @@ class SipcMessage
|
|
49
49
|
sipc_create(:command => 'S', :F => fetion.sid, :I => fetion.next_call, :Q => '1 S', :N => 'AddBuddyV4', :body => body)
|
50
50
|
end
|
51
51
|
|
52
|
-
def self.get_contact_info(fetion,
|
53
|
-
body = %Q|<args><contact uri="
|
52
|
+
def self.get_contact_info(fetion, uri)
|
53
|
+
body = %Q|<args><contact uri="#{uri}" /></args>|
|
54
54
|
sipc_create(:command => 'S', :F => fetion.sid, :I => fetion.next_call, :Q => '1 S', :N => 'GetContactInfoV4', :body => body)
|
55
55
|
end
|
56
56
|
|
@@ -66,7 +66,7 @@ class SipcMessage
|
|
66
66
|
body = options.delete(:body)
|
67
67
|
with_l = options.delete(:with_l)
|
68
68
|
|
69
|
-
sorted_key = [:F, :I, :Q, :CN, :CL, :A, :AK, :X, :T, :
|
69
|
+
sorted_key = [:F, :I, :Q, :CN, :CL, :A, :AK, :X, :T, :K, :N, :SV]
|
70
70
|
sipc = "#{options.delete(:command)} fetion.com.cn SIP-C/4.0\r\n"
|
71
71
|
sorted_key.each {|k| sipc += "#{k}: #{options[k]}\r\n" if options[k]}
|
72
72
|
sipc += "L: #{body == '' ? 4 : body.size}\r\n" if with_l
|
@@ -75,8 +75,10 @@ class SipcMessage
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def self.sipc_response(http_response_body)
|
78
|
-
sipc, code, message = http_response_body.
|
78
|
+
sipc, code, message = http_response_body.split(/(\r)?\n/).first.split(' ')
|
79
79
|
RESPONSES[code.to_i].new(code, message)
|
80
|
+
rescue NoMethodError
|
81
|
+
raise FetionException.new("Fetion error: No response to #{code} #{message}")
|
80
82
|
end
|
81
83
|
|
82
84
|
class Response
|
@@ -93,11 +95,17 @@ class SipcMessage
|
|
93
95
|
end
|
94
96
|
|
95
97
|
class OK < Response; end
|
98
|
+
class Send < Response; end
|
99
|
+
class Bad < Response; end
|
100
|
+
class Unauthoried < Response; end
|
96
101
|
class NotFound < Response; end
|
97
102
|
class ExtentionRequired < Response; end
|
98
103
|
|
99
104
|
RESPONSES = {
|
100
105
|
200 => SipcMessage::OK,
|
106
|
+
280 => SipcMessage::Send,
|
107
|
+
400 => SipcMessage::Bad,
|
108
|
+
401 => SipcMessage::Unauthoried,
|
101
109
|
404 => SipcMessage::NotFound,
|
102
110
|
421 => SipcMessage::ExtentionRequired
|
103
111
|
}
|
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.1"
|
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-10}
|
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"]
|
data/spec/rfetion/fetion_spec.rb
CHANGED
@@ -57,10 +57,10 @@ describe SipcMessage do
|
|
57
57
|
SipcMessage.send_cat_sms(@fetion, 'sip:730020377@fetion.com.cn;p=6907', 'test').should == sipc_message
|
58
58
|
end
|
59
59
|
|
60
|
-
it "should send msg" do
|
60
|
+
it "should send cat msg" do
|
61
61
|
@fetion.call = 8
|
62
|
-
sipc_message = %Q|M fetion.com.cn SIP-C/4.0\r\nF: 730020377\r\nI: 9\r\nQ:
|
63
|
-
SipcMessage.
|
62
|
+
sipc_message = %Q|M fetion.com.cn SIP-C/4.0\r\nF: 730020377\r\nI: 9\r\nQ: 2 M\r\nT: sip:638993408@fetion.com.cn;p=2242\r\nK: SaveHistory\r\nN: CatMsg\r\nL: 4\r\n\r\ntestSIPP|
|
63
|
+
SipcMessage.send_cat_msg(@fetion, 'sip:638993408@fetion.com.cn;p=2242', 'test').should == sipc_message
|
64
64
|
end
|
65
65
|
|
66
66
|
it "should set schedule sms" do
|
@@ -72,7 +72,7 @@ describe SipcMessage do
|
|
72
72
|
it "should get contact info" do
|
73
73
|
@fetion.call = 10
|
74
74
|
sipc_message = %Q|S fetion.com.cn SIP-C/4.0\r\nF: 730020377\r\nI: 11\r\nQ: 1 S\r\nN: GetContactInfoV4\r\nL: 46\r\n\r\n<args><contact uri="tel:15800681507" /></args>SIPP|
|
75
|
-
SipcMessage.get_contact_info(@fetion, 15800681507).should == sipc_message
|
75
|
+
SipcMessage.get_contact_info(@fetion, "tel:15800681507").should == sipc_message
|
76
76
|
end
|
77
77
|
|
78
78
|
it "should add buddy" do
|
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.1
|
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-10 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|