From 384ffd58ddc4e03ff41f887fc3b1bf90083114de Mon Sep 17 00:00:00 2001 From: Parnic Date: Thu, 5 Apr 2018 20:51:48 -0500 Subject: [PATCH] Initial commit --- .gitignore | 24 +++++++++ Gemfile | 3 ++ LICENSE | 21 ++++++++ README.md | 45 +++++++++++++++++ Rakefile | 5 ++ lib/shift_stats.rb | 87 ++++++++++++++++++++++++++++++++ lib/shift_stats/configuration.rb | 9 ++++ shift_stats.gemspec | 15 ++++++ spec/shift_stats_spec.rb | 62 +++++++++++++++++++++++ spec/spec_helper.rb | 1 + 10 files changed, 272 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Rakefile create mode 100644 lib/shift_stats.rb create mode 100644 lib/shift_stats/configuration.rb create mode 100644 shift_stats.gemspec create mode 100644 spec/shift_stats_spec.rb create mode 100644 spec/spec_helper.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d2c67b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +*.gem +*.rbc +*.sassc +.bundle +.config +.yardoc +.rvmrc +.rspec +.sass-cache +.DS_Store +Gemfile.lock +InstalledFiles +_yardoc +doc/ +coverage +lib/bundler/man +capybara-*.html +pkg +rdoc +spec/reports +spec/tmp +test/tmp +test/version_tmp +tmp diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..a1b93f3 --- /dev/null +++ b/Gemfile @@ -0,0 +1,3 @@ +source :rubygems + +gemspec diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b442934 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f06650f --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# ShiftStats gem +This gem pulls data from Digital Shift sites such as HockeyShift, SoccerShift, LacrosseShift, FootballShift, BasketballShift, and BaseballShift. +[![Gem Version](https://badge.fury.io/rb/shift_stats.svg)](http://badge.fury.io/rb/shift_stats) + +## Features +* Get details about any team for any sport +* Get a specific team's game schedule +* Retrieve the list of players on a specific team +* Find all games for a specific division +* Find all divisions in a specific season + +## Install +You can install shift_stats via rubygems: `gem install shift_stats` + +## Usage + +```ruby +require 'shift_stats' +``` + +Optionally configure your API key (note: by default uses the same API key as the Android HockeyShift app) + +```ruby +ShiftStats.configure do |config| + config.api_key 'my_api_key' +end +``` + +Create a new instance of ShiftSats with `s = new ShiftStats`. This connects to the ShiftStats server, logs in, and stores the ticket hash. This ticket is only valid for a limited amount of time. + +Creating an instance of the class can raise an error if there are network issues or the API key is invalid. + +### Available methods + +* `team_search(sport_name, team_name)` - Search for the given team in the given sport for all active seasons. +* `team_schedule(team_id)` - Retrieve the game schedule for the supplied team. +* `team_players_list(team_id)` - Get the list of players on a specific team. +* `division_games_list(division_id)` - Returns all games for a specified division. +* `season_divisions_list(season_id)` - Lists all divisions for the specified season. + +## Bug reports, feature requests, contributions + +Please create an issue or pull request on github. Assistance is most welcome. + +There are many more endpoints available on Shift sites, but none are documented. Running a mobile app inside an emulator and watching wireshark, fiddler, etc. is how the current endpoints were discovered. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..f34a48c --- /dev/null +++ b/Rakefile @@ -0,0 +1,5 @@ +require 'rspec/core/rake_task' + +RSpec::Core::RakeTask.new(:spec) + +task default: :spec diff --git a/lib/shift_stats.rb b/lib/shift_stats.rb new file mode 100644 index 0000000..37a3cd5 --- /dev/null +++ b/lib/shift_stats.rb @@ -0,0 +1,87 @@ +require 'httpclient' +require 'json' +require 'shift_stats/configuration' + +class ShiftStats + class << self + attr_accessor :configuration + end + + def self.configuration + @configuration ||= Configuration.new + end + + def self.reset + @configuration = Configuration.new + end + + def self.configure + yield(configuration) + end + + def initialize + @url_base = 'http://api.shiftstats.com/' + @ticket_hash = nil + + @client = HTTPClient.new + @client.transparent_gzip_decompression = true + + response = @client.get(url('login'), query: login_query, header: basic_headers) + response_json = JSON.parse(response.body) if response + if response_json && response_json['ticket'] && response_json['ticket']['hash'] + @ticket_hash = response_json['ticket']['hash'] + else + if response && response.body + raise response.body + else + raise "Unknown error. Make sure you have an internet connection and your API key is correct." + end + end + end + + def team_search(sport, name) + JSON.parse(@client.get(url('teams'), query: {name: name, not_ended: true, sport: sport.downcase}, header: headers).body) + end + + def team_schedule(team_id) + JSON.parse(@client.get(url("team/#{team_id}/games"), query: {future: true, today: true, past: true}, header: headers).body) + end + + def team_players_list(team_id) + JSON.parse(@client.get(url("team/#{team_id}/players"), query: {status: 'active'}, header: headers).body) + end + + def division_games_list(division_id) + JSON.parse(@client.get(url("division/#{division_id}/games"), header: headers).body) + end + + def season_divisions_list(season_id) + JSON.parse(@client.get(url("season/#{season_id}/divisions"), header: headers).body) + end + + private + def url(sub) + return "#{@url_base}#{sub}" + end + + def login_query + {key: self.class.configuration.api_key} + end + + def basic_headers + { + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + 'X-Requested-With' => 'com.digitalshift.hockeyshift', + 'Accept-Language' => 'en-US', + 'Accept-Encoding' => 'gzip,deflate', + 'Connection' => 'keep-alive', + } + end + + def headers + basic_headers.merge({ + 'Authorization' => "StatsAuth ticket=\"#{@ticket_hash}\"" + }) + end +end diff --git a/lib/shift_stats/configuration.rb b/lib/shift_stats/configuration.rb new file mode 100644 index 0000000..3477d31 --- /dev/null +++ b/lib/shift_stats/configuration.rb @@ -0,0 +1,9 @@ +class ShiftStats + class Configuration + attr_accessor :api_key + + def initialize + @api_key = 'YXBpLnNoaWZ0c3RhdHMuY29tLDE5YjhhZGIwNDVjZjAxMzJhM2E5N2VmZDQ1YTRj' + end + end +end diff --git a/shift_stats.gemspec b/shift_stats.gemspec new file mode 100644 index 0000000..3bca148 --- /dev/null +++ b/shift_stats.gemspec @@ -0,0 +1,15 @@ +Gem::Specification.new do |s| + s.name = 'shift_stats' + s.version = '0.0.1' + s.date = '2018-04-05' + s.summary = 'Shift stats API' + s.description = 'Interfaces with Digital Shift APIs (HockeyShift, BasketballShift, etc.)' + s.authors = ['Chris Pickett'] + s.email = 'chris@parnic.com' + s.files = ['lib/shift_stats.rb', 'lib/shift_stats/configuration.rb'] + s.homepage = 'https://github.com/parnic/shift_stats' + s.license = 'MIT' + s.add_runtime_dependency 'httpclient', '~> 2' + s.add_development_dependency 'rake', '~> 0' + s.add_development_dependency 'rspec', '~> 0' +end diff --git a/spec/shift_stats_spec.rb b/spec/shift_stats_spec.rb new file mode 100644 index 0000000..666901a --- /dev/null +++ b/spec/shift_stats_spec.rb @@ -0,0 +1,62 @@ +require 'spec_helper' + +describe ShiftStats do + describe 'bad api key' do + it 'throws an error' do + ShiftStats.configure {|config| config.api_key = 'a'} + expect {ShiftStats.new}.to raise_error RuntimeError + end + end + + describe 'with valid api key' do + s = ShiftStats.new + team_search = s.team_search('hockey', 'bears') + + context 'team_search' do + it 'returns something' do + expect(team_search).to be_truthy + end + + it 'returns some teams' do + expect(team_search).to include 'teams' + end + + it 'finds the right team' do + bears = team_search['teams'].select{|team| team['id'] == 18827}.first + expect(bears).to be_truthy + end + end + + context 'team_schedule' do + team_schedule = s.team_schedule(18827) + + it 'returns something' do + expect(team_schedule).to be_truthy + end + end + + context 'team_players_list' do + team_players = s.team_players_list(18827) + + it 'returns something' do + expect(team_players).to be_truthy + end + end + + context 'division_games_list' do + division_games = s.division_games_list(3057) + + it 'returns something' do + expect(division_games).to be_truthy + end + end + + context 'season_divisions_list' do + season_divisions = s.season_divisions_list(741) + + it 'returns something' do + expect(season_divisions).to be_truthy + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..4250020 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1 @@ +require 'shift_stats'