rfetion 0.5.6 → 0.5.7
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/Rakefile +3 -1
- data/VERSION +1 -1
- data/lib/rfetion/buddy_list.rb +2 -2
- data/lib/rfetion/contact.rb +5 -4
- data/lib/rfetion/fetion.rb +23 -15
- data/lib/rfetion/pic_certificate.rb +10 -5
- data/lib/rfetion/sipc_message.rb +1 -1
- data/rfetion.gemspec +11 -5
- data/spec/rfetion/buddy_list_spec.rb +10 -1
- data/spec/rfetion/fetion_spec.rb +4 -2
- data/spec/rfetion/sipc_message_spec.rb +1 -0
- metadata +28 -6
data/Rakefile
CHANGED
@@ -29,8 +29,10 @@ Jeweler::Tasks.new do |gemspec|
|
|
29
29
|
gemspec.homepage = 'http://github.com/flyerhzm/rfetion'
|
30
30
|
gemspec.authors = ['Richard Huang']
|
31
31
|
gemspec.files.exclude '.gitignore'
|
32
|
-
gemspec.add_dependency 'guid'
|
32
|
+
gemspec.add_dependency 'guid'
|
33
33
|
gemspec.add_dependency 'nokogiri'
|
34
|
+
gemspec.add_dependency 'json'
|
35
|
+
gemspec.add_dependency 'macaddr'
|
34
36
|
gemspec.executables << 'rfetion'
|
35
37
|
end
|
36
38
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.7
|
data/lib/rfetion/buddy_list.rb
CHANGED
@@ -8,8 +8,8 @@ class Fetion
|
|
8
8
|
@contacts = []
|
9
9
|
end
|
10
10
|
|
11
|
-
def to_json
|
12
|
-
{:bid => @bid, :name => @name, :contacts => @contacts}.to_json
|
11
|
+
def to_json(*args)
|
12
|
+
{:bid => @bid, :name => @name, :contacts => @contacts, :total_contacts => total_contacts_count, :online_contacts => online_contacts_count}.to_json(*args)
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.parse(buddy_list)
|
data/lib/rfetion/contact.rb
CHANGED
@@ -10,8 +10,8 @@ class Fetion
|
|
10
10
|
"0" => "脱机"
|
11
11
|
}
|
12
12
|
|
13
|
-
def to_json
|
14
|
-
{:uid => @uid, :sid => @sid, :bid => @bid, :uri => @uri, :mobile_no => @mobile_no, :nickname => @nickname, :impresa => @impresa, :status => @status}.to_json
|
13
|
+
def to_json(*args)
|
14
|
+
{:uid => @uid, :sid => @sid, :bid => @bid, :uri => @uri, :mobile_no => @mobile_no, :nickname => @nickname, :impresa => @impresa, :status => @status, :display => display}.to_json(*args)
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.parse_buddy(b)
|
@@ -28,18 +28,19 @@ class Fetion
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def initialize(options={})
|
31
|
+
@status = "0"
|
31
32
|
options.each do |key, value|
|
32
33
|
send("#{key}=", value)
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
def update(p)
|
37
|
+
def update(p, pr)
|
37
38
|
self.sid = p["sid"] if p["sid"] and !p["sid"].empty?
|
38
39
|
self.uri = p["su"] if p["su"] and !p["su"].empty?
|
39
40
|
self.mobile_no = p["m"] if p["m"] and !p["m"].empty?
|
40
41
|
self.nickname = p["n"] if p["n"] and !p["n"].empty?
|
41
42
|
self.impresa = p["i"] if p["i"] and !p["i"].empty?
|
42
|
-
self.status =
|
43
|
+
self.status = pr["b"] if pr["b"] and !pr["b"].empty?
|
43
44
|
end
|
44
45
|
|
45
46
|
def display
|
data/lib/rfetion/fetion.rb
CHANGED
@@ -1,15 +1,18 @@
|
|
1
|
+
#coding: utf-8
|
1
2
|
require 'guid'
|
2
3
|
require 'time'
|
3
4
|
require 'net/http'
|
4
5
|
require 'net/https'
|
5
6
|
require 'nokogiri'
|
6
7
|
require 'digest/sha1'
|
8
|
+
require 'digest/md5'
|
9
|
+
require 'macaddr'
|
7
10
|
require 'openssl'
|
8
11
|
require 'logger'
|
9
12
|
require 'json'
|
10
13
|
|
11
14
|
class Fetion
|
12
|
-
attr_accessor :mobile_no, :sid, :password, :call, :seq, :alive, :ssic, :guid, :uri
|
15
|
+
attr_accessor :mobile_no, :sid, :password, :call, :seq, :alive, :ssic, :guid, :uri, :pid, :pic, :algorithm, :machine_code
|
13
16
|
attr_reader :uid, :buddy_lists, :add_requests, :response, :nickname, :impresa, :receives
|
14
17
|
|
15
18
|
FETION_URL = 'http://221.176.31.39/ht/sd.aspx'
|
@@ -32,8 +35,8 @@ class Fetion
|
|
32
35
|
@guid = Guid.new.to_s
|
33
36
|
end
|
34
37
|
|
35
|
-
def to_json
|
36
|
-
{:mobile_no => @mobile_no, :sid => @sid, :uid => @uid, :uri => @uri, :status_code => @status_code, :buddy_lists => @buddy_lists, :receives => @receives, :add_requests => @add_requests, :nickname => @nickname, :impresa => @impresa, :ssic => @ssic, :guid => @guid, :call => @call, :seq => @seq, :alive => @alive}.to_json
|
38
|
+
def to_json(*args)
|
39
|
+
{:mobile_no => @mobile_no, :sid => @sid, :uid => @uid, :uri => @uri, :status_code => @status_code, :buddy_lists => @buddy_lists, :receives => @receives, :add_requests => @add_requests, :nickname => @nickname, :impresa => @impresa, :ssic => @ssic, :guid => @guid, :call => @call, :seq => @seq, :alive => @alive}.to_json(*args)
|
37
40
|
end
|
38
41
|
|
39
42
|
def logger_level=(level)
|
@@ -169,7 +172,9 @@ class Fetion
|
|
169
172
|
else
|
170
173
|
url = FETION_LOGIN_URL.sub('%sid%', @sid).sub('mobileno=%mobileno%', '')
|
171
174
|
end
|
172
|
-
|
175
|
+
url.sub!('%digest%', Digest::SHA1.hexdigest("#{DOMAIN}:#{@password}"))
|
176
|
+
url += "&pid=#@pid&pic=#@pic&algorithm=#@algorithm" if @pic
|
177
|
+
uri = URI.parse(url)
|
173
178
|
http = Net::HTTP.new(uri.host, uri.port)
|
174
179
|
http.use_ssl = true
|
175
180
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
@@ -204,7 +209,6 @@ class Fetion
|
|
204
209
|
def register_second
|
205
210
|
@logger.debug "fetion register second"
|
206
211
|
|
207
|
-
body = %Q|<args><device machine-code="B04B5DA2F5F1B8D01A76C0EBC841414C" /><caps value="ff" /><events value="7f" /><user-info mobile-no="#{@mobile_no}" user-id="#{@uid}"><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>|
|
208
212
|
curl_exec(SipcMessage.register_second(self))
|
209
213
|
pulse
|
210
214
|
|
@@ -369,17 +373,17 @@ class Fetion
|
|
369
373
|
http = Net::HTTP.new(uri.host, uri.port)
|
370
374
|
headers = {'User-Agent' => USER_AGENT}
|
371
375
|
response = http.request_get(uri.request_uri, headers)
|
372
|
-
pic_certificate = parse_pic_certificate(response)
|
376
|
+
pic_certificate = parse_pic_certificate(response, algorithm)
|
373
377
|
|
374
378
|
@logger.info "fetion get pic success"
|
375
379
|
pic_certificate
|
376
380
|
end
|
377
381
|
|
378
382
|
def parse_ssic(response)
|
379
|
-
raise Fetion::PasswordError.new('
|
380
|
-
raise Fetion::PasswordMaxError.new('
|
381
|
-
raise Fetion::LoginException.new('
|
382
|
-
raise Fetion::LoginException.new('
|
383
|
+
raise Fetion::PasswordError.new('帐号或密码不正确') if Net::HTTPUnauthorized === response
|
384
|
+
raise Fetion::PasswordMaxError.new('您已连续输入错误密码,为了保障您的帐户安全,请输入图形验证码:') if Net::HTTPClientError === response
|
385
|
+
raise Fetion::LoginException.new('Login failed.') unless Net::HTTPSuccess === response
|
386
|
+
raise Fetion::LoginException.new('No ssic found in cookie.') unless response['set-cookie'] =~ /ssic=(.*);/
|
383
387
|
|
384
388
|
@ssic = $1
|
385
389
|
@logger.debug response.body
|
@@ -404,11 +408,11 @@ class Fetion
|
|
404
408
|
@logger.debug "sid: " + @sid
|
405
409
|
end
|
406
410
|
|
407
|
-
def parse_pic_certificate(response)
|
408
|
-
raise FetionException.new('
|
411
|
+
def parse_pic_certificate(response, algorithm)
|
412
|
+
raise FetionException.new('Get verification code failed.') unless Net::HTTPSuccess === response
|
409
413
|
doc = Nokogiri::XML(response.body)
|
410
414
|
certificate = doc.root.xpath('/results/pic-certificate').first
|
411
|
-
PicCertificate.parse(certificate)
|
415
|
+
PicCertificate.parse(certificate, algorithm)
|
412
416
|
end
|
413
417
|
|
414
418
|
def curl_exec(body='', url=next_url, expected=SipcMessage::OK)
|
@@ -433,7 +437,7 @@ class Fetion
|
|
433
437
|
|
434
438
|
if sipc_response.first_line =~ /401/
|
435
439
|
# unauthorized, get nonce, key and signature
|
436
|
-
raise Fetion::NoNonceException.new("
|
440
|
+
raise Fetion::NoNonceException.new("No nonce found") unless response.body =~ /nonce="(.*?)",key="(.*?)",signature="(.*?)"/
|
437
441
|
@nonce = $1
|
438
442
|
@key = $2
|
439
443
|
@signature = $3
|
@@ -485,7 +489,7 @@ class Fetion
|
|
485
489
|
unless self.uid == c['id']
|
486
490
|
contact = contacts.find {|contact| contact.uid == c['id']}
|
487
491
|
if contact
|
488
|
-
contact.update(c.children.first)
|
492
|
+
contact.update(c.children.first, c.children.last)
|
489
493
|
else
|
490
494
|
contact = Fetion::Contact.parse(c)
|
491
495
|
if @buddy_lists.size > 1
|
@@ -532,6 +536,10 @@ class Fetion
|
|
532
536
|
|
533
537
|
rsa_key.public_encrypt(str).unpack("H*").first.upcase
|
534
538
|
end
|
539
|
+
|
540
|
+
def machine_code
|
541
|
+
@machine_code ||= Digest::MD5.hexdigest(Mac.addr)
|
542
|
+
end
|
535
543
|
|
536
544
|
def self?(mobile_or_sid)
|
537
545
|
mobile_or_sid == @mobile_no or mobile_or_sid == @sid
|
@@ -1,12 +1,17 @@
|
|
1
1
|
class PicCertificate
|
2
|
-
attr_reader :
|
2
|
+
attr_reader :pid, :pic, :algorithm
|
3
3
|
|
4
|
-
def initialize(
|
5
|
-
@
|
4
|
+
def initialize(pid, pic, algorithm)
|
5
|
+
@pid = pid
|
6
6
|
@pic = pic
|
7
|
+
@algorithm = algorithm
|
7
8
|
end
|
8
9
|
|
9
|
-
def self.parse(c)
|
10
|
-
PicCertificate.new(c['id'], c['pic'])
|
10
|
+
def self.parse(c, algorithm)
|
11
|
+
PicCertificate.new(c['id'], c['pic'], algorithm)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_json(*args)
|
15
|
+
{:pid => @pid, :pic => @pic, :algorithm => @algorithm}
|
11
16
|
end
|
12
17
|
end
|
data/lib/rfetion/sipc_message.rb
CHANGED
@@ -6,7 +6,7 @@ class SipcMessage
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def self.register_second(fetion)
|
9
|
-
body = %Q|<args><device machine-code="
|
9
|
+
body = %Q|<args><device machine-code="#{fetion.machine_code}" /><caps value="ff" /><events value="7f" /><user-info mobile-no="#{fetion.mobile_no}" user-id="#{fetion.uid}"><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>|
|
10
10
|
sipc_create(:command => 'R', :F => fetion.sid, :I => 1, :Q => "#{fetion.next_alive} R", :A => %Q|Digest response="#{fetion.response}",algorithm="SHA1-sess-v4"|, :AK => 'ak-value', :body => body)
|
11
11
|
end
|
12
12
|
|
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.7"
|
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-29}
|
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"]
|
@@ -53,15 +53,21 @@ Gem::Specification.new do |s|
|
|
53
53
|
s.specification_version = 3
|
54
54
|
|
55
55
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
56
|
-
s.add_runtime_dependency(%q<guid>, [">= 0
|
56
|
+
s.add_runtime_dependency(%q<guid>, [">= 0"])
|
57
57
|
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
58
|
+
s.add_runtime_dependency(%q<json>, [">= 0"])
|
59
|
+
s.add_runtime_dependency(%q<macaddr>, [">= 0"])
|
58
60
|
else
|
59
|
-
s.add_dependency(%q<guid>, [">= 0
|
61
|
+
s.add_dependency(%q<guid>, [">= 0"])
|
60
62
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
63
|
+
s.add_dependency(%q<json>, [">= 0"])
|
64
|
+
s.add_dependency(%q<macaddr>, [">= 0"])
|
61
65
|
end
|
62
66
|
else
|
63
|
-
s.add_dependency(%q<guid>, [">= 0
|
67
|
+
s.add_dependency(%q<guid>, [">= 0"])
|
64
68
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
69
|
+
s.add_dependency(%q<json>, [">= 0"])
|
70
|
+
s.add_dependency(%q<macaddr>, [">= 0"])
|
65
71
|
end
|
66
72
|
end
|
67
73
|
|
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/../spec_helper.rb'
|
|
2
2
|
|
3
3
|
describe Fetion::BuddyList do
|
4
4
|
before :each do
|
5
|
-
@buddy_list = Fetion::BuddyList.new("1", "
|
5
|
+
@buddy_list = Fetion::BuddyList.new("1", "My friend")
|
6
6
|
@buddy_list.add_contact(Fetion::Contact.new(:uid => "226911221", :uri => "sip:572512981@fetion.com.cn;p=3544", :bid => "1", :status => "400"))
|
7
7
|
@buddy_list.add_contact(Fetion::Contact.new(:uid => "295098062", :uri => "sip:638993408@fetion.com.cn;p=2242", :bid => "1"))
|
8
8
|
@buddy_list.add_contact(Fetion::Contact.new(:uid => "579113578", :uri => "sip:838271744@fetion.com.cn;p=4805", :bid => "1"))
|
@@ -19,4 +19,13 @@ describe Fetion::BuddyList do
|
|
19
19
|
it "should get online contacts count" do
|
20
20
|
@buddy_list.online_contacts_count.should == 3
|
21
21
|
end
|
22
|
+
|
23
|
+
it "should to_json" do
|
24
|
+
buddy_list_json = @buddy_list.to_json
|
25
|
+
p buddy_list_json
|
26
|
+
buddy_list_json.should be_include %Q|"bid":"1"|
|
27
|
+
buddy_list_json.should be_include %Q|"name":"My friend"|
|
28
|
+
buddy_list_json.should be_include %Q|"total_contacts":7|
|
29
|
+
buddy_list_json.should be_include %Q|"online_contacts":3|
|
30
|
+
end
|
22
31
|
end
|
data/spec/rfetion/fetion_spec.rb
CHANGED
@@ -312,6 +312,7 @@ EOF
|
|
312
312
|
FakeWeb.register_uri(:post, "http://221.176.31.39/ht/sd.aspx?t=s&i=10", :body => response_body)
|
313
313
|
@fetion.get_contacts
|
314
314
|
@fetion.contacts.collect {|contact| contact.sid}.should == ["572512981", "638993408", nil, "926157269", nil, nil, "480867781", "793401629", "669700695", "660250260", "737769829", "760087520"]
|
315
|
+
@fetion.contacts.collect {|contact| contact.status}.should == ["0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "400", "0"]
|
315
316
|
end
|
316
317
|
|
317
318
|
it "should get received msg while get contacts" do
|
@@ -832,9 +833,10 @@ EOF
|
|
832
833
|
EOF
|
833
834
|
FakeWeb.register_uri(:get, "http://nav.fetion.com.cn/nav/GetPicCodeV4.aspx?algorithm=picc-PasswordErrorMax", :body => response_body)
|
834
835
|
actual_pic = @fetion.get_pic_certificate("picc-PasswordErrorMax")
|
835
|
-
expected_pic = PicCertificate.parse(Nokogiri::XML(response_body).root.xpath('/results/pic-certificate').first)
|
836
|
-
actual_pic.
|
836
|
+
expected_pic = PicCertificate.parse(Nokogiri::XML(response_body).root.xpath('/results/pic-certificate').first, 'picc-PasswordErrorMax')
|
837
|
+
actual_pic.pid.should == expected_pic.pid
|
837
838
|
actual_pic.pic.should == expected_pic.pic
|
839
|
+
actual_pic.algorithm.should == expected_pic.algorithm
|
838
840
|
end
|
839
841
|
end
|
840
842
|
end
|
@@ -48,6 +48,7 @@ L: 447
|
|
48
48
|
<args><device machine-code="B04B5DA2F5F1B8D01A76C0EBC841414C" /><caps value="ff" /><events value="7f" /><user-info mobile-no="15800681509" user-id="390937727"><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>SIPP
|
49
49
|
EOF
|
50
50
|
sipc_message.gsub!("\n", "\r\n").chomp!
|
51
|
+
@fetion.machine_code = "B04B5DA2F5F1B8D01A76C0EBC841414C"
|
51
52
|
SipcMessage.register_second(@fetion).should == sipc_message
|
52
53
|
end
|
53
54
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 5
|
8
|
-
-
|
9
|
-
version: 0.5.
|
8
|
+
- 7
|
9
|
+
version: 0.5.7
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Richard Huang
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-29 00:00:00 +08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -26,9 +26,7 @@ dependencies:
|
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
segments:
|
28
28
|
- 0
|
29
|
-
|
30
|
-
- 1
|
31
|
-
version: 0.1.1
|
29
|
+
version: "0"
|
32
30
|
type: :runtime
|
33
31
|
version_requirements: *id001
|
34
32
|
- !ruby/object:Gem::Dependency
|
@@ -43,6 +41,30 @@ dependencies:
|
|
43
41
|
version: "0"
|
44
42
|
type: :runtime
|
45
43
|
version_requirements: *id002
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: json
|
46
|
+
prerelease: false
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
type: :runtime
|
55
|
+
version_requirements: *id003
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: macaddr
|
58
|
+
prerelease: false
|
59
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
type: :runtime
|
67
|
+
version_requirements: *id004
|
46
68
|
description: rfetion is a ruby gem for China Mobile fetion service that you can send SMS free.
|
47
69
|
email: flyerhzm@gmail.com
|
48
70
|
executables:
|