stew 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -56,17 +56,17 @@ steam_id.friends.each {|friend| puts friend.profile.nickname}
56
56
 
57
57
  ##### From an App id
58
58
  ```ruby
59
- app = Stew::StoreClient.new.create_app(220240)
59
+ app = Stew::Store::StoreClient.new.create_app(220240)
60
60
  ```
61
61
 
62
62
  ##### From a URL
63
63
  ```ruby
64
- app = Stew::StoreClient.new.create_app("http://store.steampowered.com/app/220240/")
64
+ app = Stew::Store::StoreClient.new.create_app("http://store.steampowered.com/app/220240/")
65
65
  ```
66
66
 
67
67
  ##### From a URL with a region
68
68
  ```ruby
69
- app = Stew::StoreClient.new.create_app("http://store.steampowered.com/app/220240/?cc=uk")
69
+ app = Stew::Store::StoreClient.new.create_app("http://store.steampowered.com/app/220240/?cc=uk")
70
70
  ```
71
71
 
72
72
  All the examples above will create a Stew::Store::App instance for the game Far Cry 3. You can then access data like so:
@@ -8,17 +8,20 @@ require 'money'
8
8
 
9
9
  require "stew/version"
10
10
 
11
- require 'stew/web_client'
12
- require 'stew/xml_client'
13
- require 'stew/community_client'
14
- require 'stew/store_client'
11
+ require 'stew/community/xml_client/xml_client'
12
+ require 'stew/community/xml_client/xml_client_response_profile'
13
+ require 'stew/community/xml_client/xml_client_response_games'
14
+ require 'stew/community/xml_client/xml_client_response_friends'
15
15
 
16
+ require 'stew/community/community_client'
16
17
  require 'stew/community/steam_id'
17
18
  require 'stew/community/profile'
18
19
  require 'stew/community/profile_friends'
19
20
  require 'stew/community/profile_game'
20
21
  require 'stew/community/profile_games'
21
22
 
23
+ require 'stew/store/web_client'
24
+ require 'stew/store/store_client'
22
25
  require 'stew/store/app'
23
26
  require 'stew/store/app_offers'
24
27
  require 'stew/store/app_offer'
@@ -28,10 +31,10 @@ module Stew
28
31
  Money.assume_from_symbol = true
29
32
 
30
33
  @config = {
31
- :default_community_client => CommunityClient,
32
- :default_store_client => StoreClient,
33
- :default_xml_client => XmlClient,
34
- :default_web_client => WebClient,
34
+ :default_community_client => Community::CommunityClient,
35
+ :default_store_client => Store::StoreClient,
36
+ :default_xml_client => Community::XmlClient,
37
+ :default_web_client => Store::WebClient,
35
38
  :default_region => :us
36
39
  }
37
40
 
@@ -0,0 +1,53 @@
1
+ module Stew
2
+ module Community
3
+ # Creation of all profile* objects.
4
+ # Uses a given or default XmlClient instance to communicate with the Steam API
5
+ # The main identifier for most methods is the 64-bit steam id
6
+ # @example Create a Profile
7
+ # Stew::CommunityClient.new.profile(76561197992917668) #=> Stew::Community::Profile
8
+ #
9
+ # @example Resolve a Steam Vanity name
10
+ # Stew::CommunityClient.steam_id_from_vanity_name('eekon20') #=> 76561197986383225
11
+ #
12
+ class CommunityClient
13
+ COMMUNITY_URL = 'http://steamcommunity.com'
14
+ DEFAULT_BASE_PATH = 'profiles'
15
+
16
+ # @deprecated Use CommunityClient.new.steam_id_from_vanity_name instead
17
+ def self.steam_id_from_vanity_name(vanity_name)
18
+ self.new.steam_id_from_vanity_name(vanity_name)
19
+ end
20
+
21
+ def initialize(opts = {})
22
+ @xml_client = opts[:client] || Stew.config[:default_xml_client].new(COMMUNITY_URL)
23
+ @base_path = opts[:base_path] || DEFAULT_BASE_PATH
24
+ end
25
+
26
+ def steam_id_from_vanity_name(vanity_name)
27
+ response = XmlClientResponseProfile.new(@xml_client.get("/id/#{vanity_name}"))
28
+ response.profile['steamID64'].to_i
29
+ end
30
+
31
+ def profile(steam_id)
32
+ response = XmlClientResponseProfile.new(@xml_client.get(path(steam_id)))
33
+ Community::Profile.new(response.profile)
34
+ end
35
+
36
+ def profile_games(steam_id)
37
+ response = XmlClientResponseGames.new(@xml_client.get(path(steam_id,'games')))
38
+ Community::ProfileGames.new(response.games)
39
+ end
40
+
41
+ def profile_friends(steam_id)
42
+ response = XmlClientResponseFriends.new(@xml_client.get(path(steam_id,'friends')))
43
+ Community::ProfileFriends.new(response.friends)
44
+ end
45
+
46
+ private
47
+
48
+ def path(steam_id,command=nil)
49
+ "/#{@base_path}/#{steam_id}/#{command}"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,50 @@
1
+ module Stew
2
+ module Community
3
+ # Client for accessing the steam community XML api
4
+ class XmlClient
5
+ def initialize(uri)
6
+ @connection = XmlClient.connection(uri)
7
+ end
8
+
9
+ # The Steam community is notorious for responding with error 503
10
+ # Retries up to 10 times for the same request to compensate for this
11
+ def get(path)
12
+ 10.times do
13
+ response = request(path)
14
+ return XmlClient.parse_response(response.body) unless response.status == 503
15
+ sleep 0.5
16
+ end
17
+ raise ServiceUnavailableError
18
+ end
19
+
20
+ private
21
+
22
+ def request(path)
23
+ @connection.get path do |req|
24
+ req.params['xml'] = 1
25
+ end
26
+ end
27
+
28
+ def self.connection(uri)
29
+ Faraday.new uri do |conn|
30
+ conn.response :xml, :content_type => /\bxml$/
31
+ conn.request :retry
32
+ conn.use FaradayMiddleware::FollowRedirects
33
+ conn.adapter Faraday.default_adapter
34
+ end
35
+ end
36
+
37
+ def self.parse_response(response)
38
+ raise(ObjectNotFoundError) if response.is_a?(String)
39
+ raise(ObjectNotFoundError, response['response']['error']) if response.has_key?('response')
40
+ response
41
+ end
42
+
43
+ # Raised when the Steam community API fails to respond after 10 tries
44
+ class ServiceUnavailableError < StandardError; end
45
+
46
+ # Raised when the reply is malformatted or if nothing is found
47
+ class ObjectNotFoundError < StandardError; end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,20 @@
1
+ module Stew
2
+ module Community
3
+ # A friends response from the Xml Client
4
+ class XmlClientResponseFriends
5
+ def initialize(response)
6
+ @response = response
7
+ end
8
+
9
+ def friends
10
+ has_friends? ? @response['friendsList']['friends']['friend'] : []
11
+ end
12
+
13
+ private
14
+
15
+ def has_friends?
16
+ !@response['friendsList']['friends'].nil?
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module Stew
2
+ module Community
3
+ # A games response from the Xml Client
4
+ class XmlClientResponseGames
5
+ def initialize(response)
6
+ @response = response
7
+ end
8
+
9
+ def games
10
+ has_games? ? @response['gamesList']['games']['game'] : []
11
+ end
12
+
13
+ private
14
+
15
+ def has_games?
16
+ !@response['gamesList']['games'].nil?
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ module Stew
2
+ module Community
3
+ # A profile response from the Xml Client
4
+ class XmlClientResponseProfile
5
+ def initialize(response)
6
+ @response = response
7
+ end
8
+
9
+ def profile
10
+ @response['profile']
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,41 @@
1
+ module Stew
2
+ module Store
3
+ # Creation of app objects from URLs or app_ids
4
+ #
5
+ # Can create apps for any steam region. When no region is given, it defaults to the default region in the configuration
6
+ #
7
+ # @example Creation of a Stew::Store::App from a URL
8
+ # Stew::StoreClient.new.create_app('http://store.steampowered.com/app/211420') #=> Stew::StoreClient::App
9
+ #
10
+ # @example Creation of a Stew::Store::App from an id
11
+ # Stew::StoreClient.new.create_app(211420) #=> Stew::StoreClient::App
12
+ #
13
+ # @example Creation of a Stew::Store::App from a URL with a different region
14
+ # Stew::StoreClient.new.create_app('http://store.steampowered.com/app/211420?cc=uk') #=> Stew::StoreClient::App
15
+ #
16
+ # @example Creation of a Stew::Store::App from an id and a region
17
+ # Stew::StoreClient.new.app(211420, :uk) #=> Stew::StoreClient::App
18
+ #
19
+ class StoreClient
20
+ STORE_URL = 'http://store.steampowered.com'
21
+
22
+ def initialize(opts = {})
23
+ @client = opts[:client] || Stew.config[:default_web_client].new(STORE_URL)
24
+ end
25
+
26
+ def create_app(data)
27
+ return app(data) if data.class == Fixnum
28
+ return app($1,$2) if data =~ /store.steampowered.com\/app\/([0-9]+)\/?\?cc=([a-zA-Z]{2})/
29
+ return app($1) if data =~ /store.steampowered.com\/app\/([0-9]+)/
30
+ raise AppIdNotFoundError
31
+ end
32
+
33
+ def app(app_id,region = Stew.config[:default_region])
34
+ Store::App.new(@client.get("/app/#{app_id}",:cc => region.to_sym))
35
+ end
36
+ end
37
+
38
+ # Error used when an app cannot be found
39
+ class AppIdNotFoundError < StandardError; end
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+ module Stew
2
+ module Store
3
+ # Client wrapper for performing requests to the Steam Store
4
+ class WebClient
5
+ def initialize(uri)
6
+ @connection = WebClient.connection(uri)
7
+ end
8
+
9
+ def get(path, options={})
10
+ request(path, options).body
11
+ end
12
+
13
+ private
14
+
15
+ def request(path,options={})
16
+ @connection.get(path) do |request|
17
+ request.params = options
18
+ end
19
+ end
20
+
21
+ def self.connection(uri)
22
+ Faraday.new uri do |conn|
23
+ conn.headers[:cookie] = "birthtime=365842801"
24
+ conn.request :retry
25
+ conn.use FaradayMiddleware::FollowRedirects
26
+ conn.adapter Faraday.default_adapter
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,3 @@
1
1
  module Stew
2
- VERSION = "0.5.1"
2
+ VERSION = "0.5.2"
3
3
  end
@@ -0,0 +1,5 @@
1
+ ---
2
+ friendsList:
3
+ steamID64: '76561197994486912'
4
+ steamID: dkmez
5
+ friends:
@@ -0,0 +1,5 @@
1
+ ---
2
+ gamesList:
3
+ steamID64: '76561197994486912'
4
+ steamID: dkmez
5
+ games:
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
 
5
5
  describe "Store", :vcr do
6
6
 
7
- let(:store_client){Stew::StoreClient.new}
7
+ let(:store_client){Stew::Store::StoreClient.new}
8
8
  subject{store_client.app(id)}
9
9
 
10
10
  describe "Creation of a store app with data" do
@@ -15,7 +15,7 @@ describe "Store", :vcr do
15
15
  end
16
16
 
17
17
  it "sets the score" do
18
- subject.score.should eq 85
18
+ subject.score.should be_a(Integer)
19
19
  end
20
20
 
21
21
  it "sets the release date" do
@@ -62,7 +62,7 @@ describe "Store", :vcr do
62
62
  end
63
63
 
64
64
  it "has a base price" do
65
- subject.price.should eq Money.parse("$59.99")
65
+ subject.price.currency.should eq Money.parse("$59.99").currency
66
66
  end
67
67
 
68
68
  describe "the basic offer" do
@@ -76,24 +76,8 @@ describe "Store", :vcr do
76
76
  offer.description.should be_nil
77
77
  end
78
78
 
79
- it "has the correct price" do
80
- offer.price.should eq Money.parse("$59.99")
81
- end
82
- end
83
-
84
- describe "the 4 pack" do
85
- let(:offer){subject.offers.entries[1]}
86
-
87
- it "has the correct name" do
88
- offer.name.should eq 'Borderlands 2 - 4-Pack'
89
- end
90
-
91
- it "has the correct description" do
92
- offer.description.should eq "Includes four copies of Borderlands 2 - Send the extra copies to your friends"
93
- end
94
-
95
- it "has the correct price" do
96
- offer.price.should eq Money.parse("$179.99")
79
+ it "has the correct currency" do
80
+ offer.price.currency.should eq Money.parse("$59.99").currency
97
81
  end
98
82
  end
99
83
  end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Stew::CommunityClient" do
4
+ let(:client){double('xml_client')}
5
+ subject{Stew::Community::CommunityClient.new({:client => client})}
6
+ let(:id){76561197992917668}
7
+
8
+ describe "#steam_id_from_vanity_name" do
9
+ let(:vanity_name){"foobar"}
10
+
11
+ it "calls steam_id_from_vanity_name on a new instance" do
12
+ Stew::Community::CommunityClient.any_instance.should_receive(:steam_id_from_vanity_name).with(vanity_name)
13
+ Stew::Community::CommunityClient.steam_id_from_vanity_name(vanity_name)
14
+ end
15
+ end
16
+
17
+
18
+ describe ".steam_id_from_vanity_name" do
19
+ let(:response){YAML.load_file("spec/fixtures/profiles/#{id}.yml")}
20
+ let(:name){"Somename"}
21
+
22
+ before :each do
23
+ client.should_receive(:get).with("/id/#{name}").and_return(response)
24
+ end
25
+
26
+ context "when the vanity name exists" do
27
+ it "returns the 64-bit id" do
28
+ subject.steam_id_from_vanity_name(name).should eq id
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "setting the base path" do
34
+ context "when the base path is not set" do
35
+ let(:results){YAML.load_file("spec/fixtures/profiles/#{id}.yml")}
36
+
37
+ it "should perform requests to the 'profile'" do
38
+ client.should_receive(:get).with("/profiles/#{id}/").and_return(results)
39
+ subject.profile(id)
40
+ end
41
+ end
42
+
43
+ context "when the base path is set to 'id'" do
44
+ let(:results){YAML.load_file("spec/fixtures/profiles/#{id}.yml")}
45
+ subject{Stew::Community::CommunityClient.new({:client => client, :base_path => 'id'})}
46
+
47
+ it "should perform profile-requests to the 'id'" do
48
+ client.should_receive(:get).with("/id/#{id}/").and_return(results)
49
+ subject.profile(id)
50
+ end
51
+ end
52
+ end
53
+
54
+ describe ".profile" do
55
+ let(:results){YAML.load_file("spec/fixtures/profiles/#{id}.yml")}
56
+
57
+ it "sends the correct message to its client" do
58
+ client.should_receive(:get).with("/profiles/#{id}/").and_return(results)
59
+ subject.profile(id)
60
+ end
61
+
62
+ it "creates a profile object" do
63
+ client.stub(:get).with("/profiles/#{id}/").and_return(results)
64
+ Stew::Community::Profile.should_receive(:new).with(results['profile'])
65
+ subject.profile(id)
66
+ end
67
+ end
68
+
69
+ describe ".profile_games" do
70
+ let(:results){YAML.load_file("spec/fixtures/profiles/games/#{id}.yml")}
71
+
72
+ it "sends the correct message to its client" do
73
+ client.should_receive(:get).with("/profiles/#{id}/games").and_return(results)
74
+ subject.profile_games(id)
75
+ end
76
+
77
+ it "creates a ProfileGames object" do
78
+ client.stub(:get).with("/profiles/#{id}/games").and_return(results)
79
+ Stew::Community::ProfileGames.should_receive(:new).with(results['gamesList']['games']['game'])
80
+ subject.profile_games(id)
81
+ end
82
+
83
+ context "when the profile has no games" do
84
+ let(:id){76561197994486912}
85
+
86
+ it "creates an empty ProfileGames instance if the profile has no games" do
87
+ client.stub(:get).with("/profiles/#{id}/games").and_return(results)
88
+ profile_games = subject.profile_games(id)
89
+ profile_games.entries.count.should eq 0
90
+ end
91
+ end
92
+ end
93
+
94
+ describe ".profile_friends" do
95
+ let(:results){YAML.load_file("spec/fixtures/profiles/friends/#{id}.yml")}
96
+
97
+ it "sends the correct message to its client" do
98
+ client.should_receive(:get).with("/profiles/#{id}/friends").and_return(results)
99
+ subject.profile_friends(id)
100
+ end
101
+
102
+ it "creates a ProfileFriends object" do
103
+ client.stub(:get).with("/profiles/#{id}/friends").and_return(results)
104
+ Stew::Community::ProfileFriends.should_receive(:new).with(results['friendsList']['friends']['friend'])
105
+ subject.profile_friends(id)
106
+ end
107
+
108
+ context "when the profile has no friends" do
109
+ let(:id){76561197994486912}
110
+
111
+ it "creates an empty ProfileFriends instance if the profile has no friends" do
112
+ client.stub(:get).with("/profiles/#{id}/friends").and_return(results)
113
+ profile_friends = subject.profile_friends(id)
114
+ profile_friends.entries.count.should eq 0
115
+ end
116
+ end
117
+ end
118
+ end
@@ -56,7 +56,7 @@ describe "Stew::Community::SteamId" do
56
56
  end
57
57
 
58
58
  it "should create a community client with no options" do
59
- Stew::CommunityClient.should_receive(:new).with()
59
+ Stew::Community::CommunityClient.should_receive(:new).with()
60
60
  Stew::Community::SteamId.new(id)
61
61
  end
62
62
  end
@@ -69,7 +69,7 @@ describe "Stew::Community::SteamId" do
69
69
  end
70
70
 
71
71
  it "should create a community client with the base_path option set to 'id'" do
72
- Stew::CommunityClient.should_receive(:new).with({:base_path => 'id'})
72
+ Stew::Community::CommunityClient.should_receive(:new).with({:base_path => 'id'})
73
73
  Stew::Community::SteamId.new(id)
74
74
  end
75
75
  end
@@ -1,11 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Stew::XmlClient" do
3
+ describe "Stew::Community::XmlClient" do
4
4
  let(:uri){'http://steamcommunity.com'}
5
5
  let(:results){YAML.load_file("spec/fixtures/profiles/#{id}.yml")}
6
6
  let(:id){76561197992917668}
7
7
 
8
- subject{Stew::XmlClient.new(uri)}
8
+ subject{Stew::Community::XmlClient.new(uri)}
9
9
 
10
10
  describe "#get" do
11
11
  context "when no error is found in the reply" do
@@ -15,7 +15,7 @@ describe "Stew::XmlClient" do
15
15
  stub_request(:get, "http://steamcommunity.com/profiles/#{id}?xml=1").to_return(File.new("spec/fixtures/profiles/#{id}.txt"))
16
16
  end
17
17
 
18
- it "returns a hash containing the parsed data from the steam community servers" do
18
+ it "returns the response" do
19
19
  subject.get(path).should eq results
20
20
  end
21
21
  end
@@ -29,7 +29,7 @@ describe "Stew::XmlClient" do
29
29
  end
30
30
 
31
31
  it "throws an ObjectNotFound error" do
32
- expect{subject.get(path).should}.to raise_error(Stew::XmlClient::ObjectNotFoundError)
32
+ expect{subject.get(path).should}.to raise_error(Stew::Community::XmlClient::ObjectNotFoundError)
33
33
  end
34
34
  end
35
35
  end
@@ -1,10 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Stew::StoreClient" do
3
+ describe "Stew::Store::StoreClient" do
4
4
  let(:client){double('web_client')}
5
5
  let(:response){open("spec/fixtures/store/apps/#{id}.txt")}
6
6
  let(:region){:us}
7
- subject{Stew::StoreClient.new({:client => client})}
7
+ subject{Stew::Store::StoreClient.new({:client => client})}
8
8
 
9
9
  describe ".app" do
10
10
  let(:id) {211420}
@@ -51,7 +51,7 @@ describe "Stew::StoreClient" do
51
51
  let(:url){"sodijfsdf"}
52
52
 
53
53
  it "raises a Stew::Store::AppIdNotFoundError" do
54
- expect{subject.create_app(url)}.to raise_error(Stew::AppIdNotFoundError)
54
+ expect{subject.create_app(url)}.to raise_error(Stew::Store::AppIdNotFoundError)
55
55
  end
56
56
  end
57
57
  end
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Stew::WebClient", :vcr do
3
+ describe "Stew::Store::WebClient", :vcr do
4
4
  let(:uri){'http://store.steampowered.com/'}
5
5
 
6
- subject{Stew::WebClient.new(uri)}
6
+ subject{Stew::Store::WebClient.new(uri)}
7
7
 
8
8
  describe ".get" do
9
9
  let(:id){216390}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stew
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-07 00:00:00.000000000 Z
12
+ date: 2013-02-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -299,25 +299,30 @@ files:
299
299
  - README.md
300
300
  - Rakefile
301
301
  - lib/stew.rb
302
+ - lib/stew/community/community_client.rb
302
303
  - lib/stew/community/profile.rb
303
304
  - lib/stew/community/profile_friends.rb
304
305
  - lib/stew/community/profile_game.rb
305
306
  - lib/stew/community/profile_games.rb
306
307
  - lib/stew/community/steam_id.rb
307
- - lib/stew/community_client.rb
308
+ - lib/stew/community/xml_client/xml_client.rb
309
+ - lib/stew/community/xml_client/xml_client_response_friends.rb
310
+ - lib/stew/community/xml_client/xml_client_response_games.rb
311
+ - lib/stew/community/xml_client/xml_client_response_profile.rb
308
312
  - lib/stew/store/app.rb
309
313
  - lib/stew/store/app_offer.rb
310
314
  - lib/stew/store/app_offer_sale.rb
311
315
  - lib/stew/store/app_offers.rb
312
- - lib/stew/store_client.rb
316
+ - lib/stew/store/store_client.rb
317
+ - lib/stew/store/web_client.rb
313
318
  - lib/stew/version.rb
314
- - lib/stew/web_client.rb
315
- - lib/stew/xml_client.rb
316
319
  - spec/fixtures/profiles/4d.txt
317
320
  - spec/fixtures/profiles/76561197992917668.txt
318
321
  - spec/fixtures/profiles/76561197992917668.yml
319
322
  - spec/fixtures/profiles/friends/76561197992917668.yml
323
+ - spec/fixtures/profiles/friends/76561197994486912.yml
320
324
  - spec/fixtures/profiles/games/76561197992917668.yml
325
+ - spec/fixtures/profiles/games/76561197994486912.yml
321
326
  - spec/fixtures/store/apps/16870.txt
322
327
  - spec/fixtures/store/apps/211400_offers_sale.txt
323
328
  - spec/fixtures/store/apps/211400_sale.txt
@@ -330,19 +335,19 @@ files:
330
335
  - spec/fixtures/store/apps/no_app.txt
331
336
  - spec/integration/community_integration_spec.rb
332
337
  - spec/integration/store_integration_spec.rb
338
+ - spec/lib/stew/community/community_client_spec.rb
333
339
  - spec/lib/stew/community/profile_friends_spec.rb
334
340
  - spec/lib/stew/community/profile_game_spec.rb
335
341
  - spec/lib/stew/community/profile_games_spec.rb
336
342
  - spec/lib/stew/community/profile_spec.rb
337
343
  - spec/lib/stew/community/steam_id_spec.rb
338
- - spec/lib/stew/community_client_spec.rb
344
+ - spec/lib/stew/community/xml_client/xml_client_spec.rb
339
345
  - spec/lib/stew/store/app_offer_sale_spec.rb
340
346
  - spec/lib/stew/store/app_offer_spec.rb
341
347
  - spec/lib/stew/store/app_offers_spec.rb
342
348
  - spec/lib/stew/store/app_spec.rb
343
- - spec/lib/stew/store_client_spec.rb
344
- - spec/lib/stew/web_client_spec.rb
345
- - spec/lib/stew/xml_client_spec.rb
349
+ - spec/lib/stew/store/store_client_spec.rb
350
+ - spec/lib/stew/store/web_client_spec.rb
346
351
  - spec/lib/stew_spec.rb
347
352
  - spec/spec_helper.rb
348
353
  - stew.gemspec
@@ -360,7 +365,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
360
365
  version: '0'
361
366
  segments:
362
367
  - 0
363
- hash: -4370496576353841969
368
+ hash: -5319004060931315
364
369
  required_rubygems_version: !ruby/object:Gem::Requirement
365
370
  none: false
366
371
  requirements:
@@ -369,7 +374,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
369
374
  version: '0'
370
375
  segments:
371
376
  - 0
372
- hash: -4370496576353841969
377
+ hash: -5319004060931315
373
378
  requirements: []
374
379
  rubyforge_project:
375
380
  rubygems_version: 1.8.24
@@ -381,7 +386,9 @@ test_files:
381
386
  - spec/fixtures/profiles/76561197992917668.txt
382
387
  - spec/fixtures/profiles/76561197992917668.yml
383
388
  - spec/fixtures/profiles/friends/76561197992917668.yml
389
+ - spec/fixtures/profiles/friends/76561197994486912.yml
384
390
  - spec/fixtures/profiles/games/76561197992917668.yml
391
+ - spec/fixtures/profiles/games/76561197994486912.yml
385
392
  - spec/fixtures/store/apps/16870.txt
386
393
  - spec/fixtures/store/apps/211400_offers_sale.txt
387
394
  - spec/fixtures/store/apps/211400_sale.txt
@@ -394,19 +401,19 @@ test_files:
394
401
  - spec/fixtures/store/apps/no_app.txt
395
402
  - spec/integration/community_integration_spec.rb
396
403
  - spec/integration/store_integration_spec.rb
404
+ - spec/lib/stew/community/community_client_spec.rb
397
405
  - spec/lib/stew/community/profile_friends_spec.rb
398
406
  - spec/lib/stew/community/profile_game_spec.rb
399
407
  - spec/lib/stew/community/profile_games_spec.rb
400
408
  - spec/lib/stew/community/profile_spec.rb
401
409
  - spec/lib/stew/community/steam_id_spec.rb
402
- - spec/lib/stew/community_client_spec.rb
410
+ - spec/lib/stew/community/xml_client/xml_client_spec.rb
403
411
  - spec/lib/stew/store/app_offer_sale_spec.rb
404
412
  - spec/lib/stew/store/app_offer_spec.rb
405
413
  - spec/lib/stew/store/app_offers_spec.rb
406
414
  - spec/lib/stew/store/app_spec.rb
407
- - spec/lib/stew/store_client_spec.rb
408
- - spec/lib/stew/web_client_spec.rb
409
- - spec/lib/stew/xml_client_spec.rb
415
+ - spec/lib/stew/store/store_client_spec.rb
416
+ - spec/lib/stew/store/web_client_spec.rb
410
417
  - spec/lib/stew_spec.rb
411
418
  - spec/spec_helper.rb
412
419
  has_rdoc:
@@ -1,42 +0,0 @@
1
- module Stew
2
- # Creation of all profile* objects.
3
- # Uses a given or default XmlClient instance to communicate with the Steam API
4
- # The main identifier for most methods is the 64-bit steam id
5
- # @example Create a Profile
6
- # Stew::CommunityClient.new.profile(76561197992917668) #=> Stew::Community::Profile
7
- #
8
- # @example Resolve a Steam Vanity name
9
- # Stew::CommunityClient.steam_id_from_vanity_name('eekon20') #=> 76561197986383225
10
- #
11
- class CommunityClient
12
- COMMUNITY_URL = 'http://steamcommunity.com'
13
- DEFAULT_BASE_PATH = 'profiles'
14
-
15
- def self.steam_id_from_vanity_name(vanity_name)
16
- Stew::XmlClient.new(COMMUNITY_URL).get("/id/#{vanity_name}")['profile']['steamID64'].to_i
17
- end
18
-
19
- def initialize(opts = {})
20
- @xml_client = opts[:client] || Stew.config[:default_xml_client].new(COMMUNITY_URL)
21
- @base_path = opts[:base_path] || DEFAULT_BASE_PATH
22
- end
23
-
24
- def profile(steam_id)
25
- Community::Profile.new @xml_client.get(path(steam_id))['profile']
26
- end
27
-
28
- def profile_games(steam_id)
29
- Community::ProfileGames.new @xml_client.get(path(steam_id,'games'))['gamesList']['games']['game']
30
- end
31
-
32
- def profile_friends(steam_id)
33
- Community::ProfileFriends.new @xml_client.get(path(steam_id,'friends'))['friendsList']['friends']['friend']
34
- end
35
-
36
- private
37
-
38
- def path(steam_id,command=nil)
39
- "/#{@base_path}/#{steam_id}/#{command}"
40
- end
41
- end
42
- end
@@ -1,39 +0,0 @@
1
- module Stew
2
- # Creation of app objects from URLs or app_ids
3
- #
4
- # Can create apps for any steam region. When no region is given, it defaults to the default region in the configuration
5
- #
6
- # @example Creation of a Stew::Store::App from a URL
7
- # Stew::StoreClient.new.create_app('http://store.steampowered.com/app/211420') #=> Stew::StoreClient::App
8
- #
9
- # @example Creation of a Stew::Store::App from an id
10
- # Stew::StoreClient.new.create_app(211420) #=> Stew::StoreClient::App
11
- #
12
- # @example Creation of a Stew::Store::App from a URL with a different region
13
- # Stew::StoreClient.new.create_app('http://store.steampowered.com/app/211420?cc=uk') #=> Stew::StoreClient::App
14
- #
15
- # @example Creation of a Stew::Store::App from an id and a region
16
- # Stew::StoreClient.new.app(211420, :uk) #=> Stew::StoreClient::App
17
- #
18
- class StoreClient
19
- STORE_URL = 'http://store.steampowered.com'
20
-
21
- def initialize(opts = {})
22
- @client = opts[:client] || Stew.config[:default_web_client].new(STORE_URL)
23
- end
24
-
25
- def create_app(data)
26
- return app(data) if data.class == Fixnum
27
- return app($1,$2) if data =~ /store.steampowered.com\/app\/([0-9]+)\/?\?cc=([a-zA-Z]{2})/
28
- return app($1) if data =~ /store.steampowered.com\/app\/([0-9]+)/
29
- raise AppIdNotFoundError
30
- end
31
-
32
- def app(app_id,region = Stew.config[:default_region])
33
- Store::App.new(@client.get("/app/#{app_id}",:cc => region.to_sym))
34
- end
35
- end
36
-
37
- # Error used when an app cannot be found
38
- class AppIdNotFoundError < StandardError; end
39
- end
@@ -1,30 +0,0 @@
1
- module Stew
2
-
3
- # Client wrapper for performing requests to the Steam Store
4
- class WebClient
5
- def initialize(uri)
6
- @connection = WebClient.connection(uri)
7
- end
8
-
9
- def get(path, options={})
10
- request(path, options).body
11
- end
12
-
13
- private
14
-
15
- def request(path,options={})
16
- @connection.get(path) do |request|
17
- request.params = options
18
- end
19
- end
20
-
21
- def self.connection(uri)
22
- Faraday.new uri do |conn|
23
- conn.headers[:cookie] = "birthtime=365842801"
24
- conn.request :retry
25
- conn.use FaradayMiddleware::FollowRedirects
26
- conn.adapter Faraday.default_adapter
27
- end
28
- end
29
- end
30
- end
@@ -1,49 +0,0 @@
1
- module Stew
2
-
3
- # Client for accessing the steam community XML api
4
- class XmlClient
5
- def initialize(uri)
6
- @connection = XmlClient.connection(uri)
7
- end
8
-
9
- # The Steam community is notorious for responding with error 503
10
- # Retries up to 10 times for the same request to compensate for this
11
- def get(path)
12
- 10.times do
13
- response = request(path)
14
- return XmlClient.parse_response(response.body) unless response.status == 503
15
- sleep 0.5
16
- end
17
- raise ServiceUnavailableError
18
- end
19
-
20
- private
21
-
22
- def request(path)
23
- @connection.get path do |req|
24
- req.params['xml'] = 1
25
- end
26
- end
27
-
28
- def self.connection(uri)
29
- Faraday.new uri do |conn|
30
- conn.response :xml, :content_type => /\bxml$/
31
- conn.request :retry
32
- conn.use FaradayMiddleware::FollowRedirects
33
- conn.adapter Faraday.default_adapter
34
- end
35
- end
36
-
37
- def self.parse_response(response)
38
- raise(ObjectNotFoundError) if response.is_a?(String)
39
- raise(ObjectNotFoundError, response['response']['error']) if response.has_key?('response')
40
- response
41
- end
42
-
43
- # Raised when the Steam community API fails to respond after 10 tries
44
- class ServiceUnavailableError < StandardError; end
45
-
46
- # Raised when the reply is malformatted or if nothing is found
47
- class ObjectNotFoundError < StandardError; end
48
- end
49
- end
@@ -1,88 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Stew::CommunityClient" do
4
- let(:client){double('xml_client')}
5
- subject{Stew::CommunityClient.new({:client => client})}
6
- let(:id){76561197992917668}
7
-
8
- describe "#steam_id_from_vanity_name" do
9
- let(:response){YAML.load_file("spec/fixtures/profiles/#{id}.yml")}
10
- let(:name){"Somename"}
11
-
12
- before :each do
13
- Stew::XmlClient.any_instance.should_receive(:get).with("/id/#{name}").and_return(response)
14
- end
15
-
16
- context "when the vanity name exists" do
17
- it "returns the 64-bit id" do
18
- Stew::CommunityClient.steam_id_from_vanity_name(name).should eq id
19
- end
20
- end
21
- end
22
-
23
- describe "setting the base path" do
24
- context "when the base path is not set" do
25
- let(:response){YAML.load_file("spec/fixtures/profiles/#{id}.yml")}
26
-
27
- it "should perform requests to the 'profile'" do
28
- client.should_receive(:get).with("/profiles/#{id}/").and_return(response)
29
- subject.profile(id)
30
- end
31
- end
32
-
33
- context "when the base path is set to 'id'" do
34
- let(:response){YAML.load_file("spec/fixtures/profiles/#{id}.yml")}
35
- subject{Stew::CommunityClient.new({:client => client, :base_path => 'id'})}
36
-
37
- it "should perform profile-requests to the 'id'" do
38
- client.should_receive(:get).with("/id/#{id}/").and_return(response)
39
- subject.profile(id)
40
- end
41
- end
42
- end
43
-
44
- describe ".profile" do
45
- let(:response){YAML.load_file("spec/fixtures/profiles/#{id}.yml")}
46
-
47
- it "sends the correct message to its client" do
48
- client.should_receive(:get).with("/profiles/#{id}/").and_return(response)
49
- subject.profile(id)
50
- end
51
-
52
- it "creates a profile object" do
53
- client.stub(:get).with("/profiles/#{id}/").and_return(response)
54
- Stew::Community::Profile.should_receive(:new).with(response['profile'])
55
- subject.profile(id)
56
- end
57
- end
58
-
59
- describe ".profile_games" do
60
- let(:response){YAML.load_file("spec/fixtures/profiles/games/#{id}.yml")}
61
-
62
- it "sends the correct message to its client" do
63
- client.should_receive(:get).with("/profiles/#{id}/games").and_return(response)
64
- subject.profile_games(id)
65
- end
66
-
67
- it "creates a ProfileGames object" do
68
- client.stub(:get).with("/profiles/#{id}/games").and_return(response)
69
- Stew::Community::ProfileGames.should_receive(:new).with(response['gamesList']['games']['game'])
70
- subject.profile_games(id)
71
- end
72
- end
73
-
74
- describe ".profile_friends" do
75
- let(:response){YAML.load_file("spec/fixtures/profiles/friends/#{id}.yml")}
76
-
77
- it "sends the correct message to its client" do
78
- client.should_receive(:get).with("/profiles/#{id}/friends").and_return(response)
79
- subject.profile_friends(id)
80
- end
81
-
82
- it "returns the value of the ['friendsList']['friends']['friend'] key from the response hash" do
83
- client.stub(:get).with("/profiles/#{id}/friends").and_return(response)
84
- Stew::Community::ProfileFriends.should_receive(:new).with(response['friendsList']['friends']['friend'])
85
- subject.profile_friends(id)
86
- end
87
- end
88
- end