vapor 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/.gitignore +15 -19
  2. data/.rspec +2 -0
  3. data/.rvmrc +48 -0
  4. data/Gemfile +4 -0
  5. data/{LICENSE → LICENSE.txt} +4 -2
  6. data/README.md +29 -0
  7. data/Rakefile +1 -53
  8. data/lib/vapor.rb +12 -0
  9. data/lib/vapor/api.rb +44 -0
  10. data/lib/vapor/crawler.rb +17 -0
  11. data/lib/vapor/game.rb +15 -0
  12. data/lib/vapor/games_list.rb +20 -0
  13. data/lib/vapor/user.rb +40 -0
  14. data/lib/vapor/version.rb +3 -0
  15. data/spec/cassettes/Vapor_API/fetches_player_summaries_for_an_user.yml +87 -0
  16. data/spec/cassettes/Vapor_Crawler/_games_for/fetches_a_games_list_for_an_user.yml +1306 -0
  17. data/spec/cassettes/Vapor_Game/finds_the_correct_id.yml +1107 -0
  18. data/spec/cassettes/Vapor_Game/finds_the_correct_name.yml +1107 -0
  19. data/spec/cassettes/Vapor_Game/finds_the_correct_time_spent_in_hours.yml +1133 -0
  20. data/spec/cassettes/Vapor_GamesList/creates_game_objects.yml +1113 -0
  21. data/spec/cassettes/Vapor_GamesList/has_the_right_amount_of_games.yml +1107 -0
  22. data/spec/cassettes/Vapor_User/fetches_the_right_Steam_Id_using_the_users_webpage.yml +57 -0
  23. data/spec/cassettes/Vapor_User/games/fetches_the_right_amount_of_games.yml +1195 -0
  24. data/spec/cassettes/Vapor_User/profile_info/has_a_profile_url.yml +40 -0
  25. data/spec/cassettes/Vapor_User/raises_a_valid_error_when_Steam_API_is_not_available.yml +57 -0
  26. data/spec/spec_helper.rb +17 -0
  27. data/spec/vapor/api_spec.rb +13 -0
  28. data/spec/vapor/crawler_spec.rb +15 -0
  29. data/spec/vapor/game_spec.rb +19 -0
  30. data/spec/vapor/games_list_spec.rb +13 -0
  31. data/spec/vapor/user_spec.rb +26 -0
  32. data/vapor.gemspec +28 -0
  33. metadata +213 -62
  34. data/.document +0 -5
  35. data/README.rdoc +0 -17
  36. data/VERSION +0 -1
  37. data/test/helper.rb +0 -10
  38. data/test/test_vapor.rb +0 -7
data/.gitignore CHANGED
@@ -1,21 +1,17 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
17
9
  coverage
18
- rdoc
10
+ doc/
11
+ lib/bundler/man
19
12
  pkg
20
-
21
- ## PROJECT::SPECIFIC
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
+ # Only full ruby name is supported here, for short names use:
8
+ # echo "rvm use 1.9.3" > .rvmrc
9
+ environment_id="ruby-1.9.3-p327@vapor"
10
+
11
+ # Uncomment the following lines if you want to verify rvm version per project
12
+ # rvmrc_rvm_version="1.16.5 (latest)" # 1.10.1 seams as a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+
18
+ # First we attempt to load the desired environment directly from the environment
19
+ # file. This is very fast and efficient compared to running through the entire
20
+ # CLI and selector. If you want feedback on which environment was used then
21
+ # insert the word 'use' after --create as this triggers verbose mode.
22
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
+ then
25
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
+ [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
27
+ \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
28
+ else
29
+ # If the environment file has not yet been created, use the RVM CLI to select.
30
+ rvm --create "$environment_id" || {
31
+ echo "Failed to create RVM environment '${environment_id}'."
32
+ return 1
33
+ }
34
+ fi
35
+
36
+ # If you use bundler, this might be useful to you:
37
+ # if [[ -s Gemfile ]] && {
38
+ # ! builtin command -v bundle >/dev/null ||
39
+ # builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
40
+ # }
41
+ # then
42
+ # printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
43
+ # gem install bundler
44
+ # fi
45
+ # if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
46
+ # then
47
+ # bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
48
+ # fi
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in vapor.gemspec
4
+ gemspec
@@ -1,4 +1,6 @@
1
- Copyright (c) 2009 Guillermo Iguaran
1
+ Copyright (c) 2012 Pedro Nascimento
2
+
3
+ MIT License
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining
4
6
  a copy of this software and associated documentation files (the
@@ -17,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
19
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
20
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
21
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Vapor
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'vapor'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install vapor
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile CHANGED
@@ -1,53 +1 @@
1
- require 'rubygems'
2
- require 'rake'
3
-
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "vapor"
8
- gem.summary = %Q{Minimalist Ruby library inspired in vapor.js}
9
- gem.description = %Q{All awesomest in one library}
10
- gem.email = "guilleiguaran@gmail.com"
11
- gem.homepage = "http://github.com/guilleiguaran/vapor"
12
- gem.authors = ["Guillermo Iguaran"]
13
- gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
- end
16
- Jeweler::GemcutterTasks.new
17
- rescue LoadError
18
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
- end
20
-
21
- require 'rake/testtask'
22
- Rake::TestTask.new(:test) do |test|
23
- test.libs << 'lib' << 'test'
24
- test.pattern = 'test/**/test_*.rb'
25
- test.verbose = true
26
- end
27
-
28
- begin
29
- require 'rcov/rcovtask'
30
- Rcov::RcovTask.new do |test|
31
- test.libs << 'test'
32
- test.pattern = 'test/**/test_*.rb'
33
- test.verbose = true
34
- end
35
- rescue LoadError
36
- task :rcov do
37
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
- end
39
- end
40
-
41
- task :test => :check_dependencies
42
-
43
- task :default => :test
44
-
45
- require 'rake/rdoctask'
46
- Rake::RDocTask.new do |rdoc|
47
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
-
49
- rdoc.rdoc_dir = 'rdoc'
50
- rdoc.title = "vapor #{version}"
51
- rdoc.rdoc_files.include('README*')
52
- rdoc.rdoc_files.include('lib/**/*.rb')
53
- end
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,12 @@
1
+ require "vapor/version"
2
+ require 'vapor/api'
3
+ require 'vapor/crawler'
4
+ require 'vapor/user'
5
+ require 'vapor/game'
6
+ require 'vapor/games_list'
7
+
8
+ module Vapor
9
+ def self.api
10
+ @@api ||= Vapor::API.new
11
+ end
12
+ end
@@ -0,0 +1,44 @@
1
+ require 'active_support/all'
2
+ require 'json'
3
+ module Vapor
4
+ class API
5
+ class << self
6
+ def key
7
+ @key ||= ENV['STEAM_API_KEY']
8
+ end
9
+ end
10
+ BASE_URL="http://api.steampowered.com"
11
+ attr_reader :client
12
+
13
+ def player_summaries_for(user)
14
+ fetch('ISteamUser/GetPlayerSummaries', version: 'v0002', steamids: user.steam_id.to_s)
15
+ end
16
+
17
+ def client
18
+ @client ||= HTTPClient.new
19
+ end
20
+
21
+ private
22
+ def fetch(url, options)
23
+ version = options.delete :version
24
+ options.merge! key: self.class.key
25
+ response = client.get("#{BASE_URL}/#{url}/#{version}/?#{normalize_params options}")
26
+ parse_and_extract_response response
27
+ end
28
+
29
+ def normalize_params(params)
30
+ query = ""
31
+ params.each {|k, v| query += "#{k}=#{v}&"}
32
+ query
33
+ end
34
+
35
+ def parse_and_extract_response(response)
36
+ JSON.parse(response.body)["response"]["players"].first.symbolize_keys
37
+ end
38
+ end
39
+ class APINotAvailableError < StandardError
40
+ def initialize
41
+ super("Steam API is currently unavailable")
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,17 @@
1
+ require 'nokogiri'
2
+ module Vapor
3
+ class Crawler
4
+ def games_for(user)
5
+ doc = fetch("#{user.profile_url}games")
6
+ doc.gamesList.games.elements
7
+ end
8
+ private
9
+ def fetch(url)
10
+ doc = client.get("#{url}?xml=1").body
11
+ Nokogiri::Slop(doc)
12
+ end
13
+ def client
14
+ @client ||= HTTPClient.new
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module Vapor
2
+ class Game
3
+ attr_reader :id, :name, :url, :time_spent_in_hours
4
+ def initialize(xml_node)
5
+ parse_xml(xml_node)
6
+ end
7
+ private
8
+ def parse_xml(xml_node)
9
+ @id = xml_node.search('appID').text.to_i
10
+ @name = xml_node.search('name').text
11
+ @url = xml_node.search('storeLink').text
12
+ @time_spent_in_hours = xml_node.search('hoursOnRecord').text.to_f
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ module Vapor
2
+ class GamesList
3
+ def initialize(user)
4
+ @user = user
5
+ end
6
+
7
+ def games
8
+ parse_games(fetch_games)
9
+ end
10
+
11
+ private
12
+ def fetch_games
13
+ Crawler.new.games_for(@user)
14
+ end
15
+
16
+ def parse_games(xml_nodes)
17
+ @games ||= xml_nodes.map{|xml| Game.new(xml)}
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ require 'httpclient'
2
+ require 'rexml/document'
3
+ module Vapor
4
+ class User
5
+ attr_reader :steam_id
6
+
7
+ def initialize(steam_id)
8
+ if steam_id.is_a? Integer || steam_id =~ /\A\d+\Z/
9
+ @steam_id = steam_id
10
+ else
11
+ @steam_id = fetch_real_id steam_id
12
+ end
13
+ @steam_id = @steam_id.to_i
14
+ end
15
+
16
+ def profile_url
17
+ @profile_url ||= player_info[:profileurl]
18
+ end
19
+
20
+ def games
21
+ @games ||= GamesList.new(self).games
22
+ end
23
+
24
+ private
25
+
26
+ def player_info
27
+ @player_info ||= Vapor.api.player_summaries_for(self)
28
+ end
29
+
30
+ def fetch_real_id(username)
31
+ user_page = client.get("http://steamcommunity.com/id/#{username}?xml=1")
32
+ raise APINotAvailableError if user_page.status == 503
33
+ REXML::Document.new(user_page.body).elements['profile/steamID64'].text
34
+ end
35
+
36
+ def client
37
+ Vapor.api.client
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module Vapor
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,87 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=8BDCBAAA1E46E207931AA2950110AEB2&steamids=76561198021477729
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: !binary |-
14
+ T0s=
15
+ headers:
16
+ !binary "RGF0ZQ==":
17
+ - !binary |-
18
+ VHVlLCAyNyBOb3YgMjAxMiAwNjoxNjozMyBHTVQ=
19
+ !binary "RXhwaXJlcw==":
20
+ - !binary |-
21
+ VHVlLCAyNyBOb3YgMjAxMiAwNjoxNjozMyBHTVQ=
22
+ !binary "Q29udGVudC1UeXBl":
23
+ - !binary |-
24
+ YXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOA==
25
+ !binary "Q29udGVudC1MZW5ndGg=":
26
+ - !binary |-
27
+ ODE0
28
+ body:
29
+ encoding: US-ASCII
30
+ string: ! "{\n\t\"response\": {\n\t\t\"players\": [\n\t\t\t{\n\t\t\t\t\"steamid\":
31
+ \"76561198021477729\",\n\t\t\t\t\"communityvisibilitystate\": 3,\n\t\t\t\t\"profilestate\":
32
+ 1,\n\t\t\t\t\"personaname\": \"Lunks\",\n\t\t\t\t\"lastlogoff\": 1353928831,\n\t\t\t\t\"profileurl\":
33
+ \"http://steamcommunity.com/id/pedronascimento/\",\n\t\t\t\t\"avatar\": \"http://media.steampowered.com/steamcommunity/public/images/avatars/4c/4c76064be169987500e4c7e228aabe3e33e1df47.jpg\",\n\t\t\t\t\"avatarmedium\":
34
+ \"http://media.steampowered.com/steamcommunity/public/images/avatars/4c/4c76064be169987500e4c7e228aabe3e33e1df47_medium.jpg\",\n\t\t\t\t\"avatarfull\":
35
+ \"http://media.steampowered.com/steamcommunity/public/images/avatars/4c/4c76064be169987500e4c7e228aabe3e33e1df47_full.jpg\",\n\t\t\t\t\"personastate\":
36
+ 1,\n\t\t\t\t\"primaryclanid\": \"103582791429521408\",\n\t\t\t\t\"timecreated\":
37
+ 1266769126,\n\t\t\t\t\"loccountrycode\": \"BR\"\n\t\t\t}\n\t\t]\n\t\t\n\t}\n}"
38
+ http_version:
39
+ recorded_at: Tue, 27 Nov 2012 06:16:25 GMT
40
+ - request:
41
+ method: get
42
+ uri: http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=&steamids=76561198021477729
43
+ body:
44
+ encoding: US-ASCII
45
+ string: ''
46
+ headers: {}
47
+ response:
48
+ status:
49
+ code: 401
50
+ message: !binary |-
51
+ VW5hdXRob3JpemVk
52
+ headers:
53
+ !binary "Q29udGVudC1MZW5ndGg=":
54
+ - !binary |-
55
+ OTg=
56
+ !binary "Q29udGVudC1UeXBl":
57
+ - !binary |-
58
+ dGV4dC9odG1sOyBjaGFyc2V0PVVURjg=
59
+ !binary "RGF0ZQ==":
60
+ - !binary |-
61
+ TW9uLCAwMyBEZWMgMjAxMiAxNjo1NzoxMyBHTVQ=
62
+ !binary "RXhwaXJlcw==":
63
+ - !binary |-
64
+ TW9uLCAyNiBKdWwgMTk5NyAwNTowMDowMCBHTVQ=
65
+ !binary "Q2FjaGUtQ29udHJvbA==":
66
+ - !binary |-
67
+ bm8tY2FjaGUsbXVzdC1yZXZhbGlkYXRl
68
+ body:
69
+ encoding: US-ASCII
70
+ string: ! '<html>
71
+
72
+ <head>
73
+
74
+ <title>401 Unauthorized</title>
75
+
76
+ </head>
77
+
78
+ <body>
79
+
80
+ <h1>Unauthorized</h1>
81
+
82
+ </body>
83
+
84
+ </html>'
85
+ http_version:
86
+ recorded_at: Mon, 03 Dec 2012 16:57:11 GMT
87
+ recorded_with: VCR 2.3.0