squash_matrix 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/Gemfile.lock +23 -13
- data/README.md +93 -4
- data/lib/squash_matrix/client.rb +62 -49
- data/lib/squash_matrix/constants.rb +13 -2
- data/lib/squash_matrix/errors.rb +1 -0
- data/lib/squash_matrix/nokogiri-parser.rb +111 -104
- data/lib/squash_matrix/version.rb +1 -1
- data/squash_matrix.gemspec +4 -3
- metadata +40 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c7451a0708b8453d1b01238019f90ce0cb6ba9a
|
4
|
+
data.tar.gz: c30bf4f51f4d4052088790229cf7becfdf6601b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa4f3f77ddd2cd63a8d230cc1dd2e3c182073fd6576d942c4b402a9c1a337edafdaf0d7a321169843e4aed972779e2d03748df209d6e67a8a64fdc91dcf4922b
|
7
|
+
data.tar.gz: f307aa98a263ad7f7a860b641691acb50a76c227c4b3b5c73eb302f5edb3691fa86af768c6e5b4f1a0c7d82a104f5cad456917aa9f23370c308719ad0228fdd8
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -2,13 +2,19 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
squash_matrix (0.1.0)
|
5
|
-
|
5
|
+
http-cookie (~> 1.0, >= 1.0.3)
|
6
|
+
nokogiri (~> 1.8, >= 1.8.4)
|
7
|
+
user-agent-randomizer (~> 0.2)
|
6
8
|
|
7
9
|
GEM
|
8
10
|
remote: https://rubygems.org/
|
9
11
|
specs:
|
10
12
|
coderay (1.1.2)
|
11
13
|
diff-lcs (1.3)
|
14
|
+
domain_name (0.5.20180417)
|
15
|
+
unf (>= 0.0.5, < 1.0.0)
|
16
|
+
http-cookie (1.0.3)
|
17
|
+
domain_name (~> 0.5)
|
12
18
|
method_source (0.8.2)
|
13
19
|
mini_portile2 (2.3.0)
|
14
20
|
nokogiri (1.8.4)
|
@@ -18,20 +24,24 @@ GEM
|
|
18
24
|
method_source (~> 0.8.1)
|
19
25
|
slop (~> 3.4)
|
20
26
|
rake (10.5.0)
|
21
|
-
rspec (3.
|
22
|
-
rspec-core (~> 3.
|
23
|
-
rspec-expectations (~> 3.
|
24
|
-
rspec-mocks (~> 3.
|
25
|
-
rspec-core (3.
|
26
|
-
rspec-support (~> 3.
|
27
|
-
rspec-expectations (3.
|
27
|
+
rspec (3.8.0)
|
28
|
+
rspec-core (~> 3.8.0)
|
29
|
+
rspec-expectations (~> 3.8.0)
|
30
|
+
rspec-mocks (~> 3.8.0)
|
31
|
+
rspec-core (3.8.0)
|
32
|
+
rspec-support (~> 3.8.0)
|
33
|
+
rspec-expectations (3.8.1)
|
28
34
|
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
-
rspec-support (~> 3.
|
30
|
-
rspec-mocks (3.
|
35
|
+
rspec-support (~> 3.8.0)
|
36
|
+
rspec-mocks (3.8.0)
|
31
37
|
diff-lcs (>= 1.2.0, < 2.0)
|
32
|
-
rspec-support (~> 3.
|
33
|
-
rspec-support (3.
|
38
|
+
rspec-support (~> 3.8.0)
|
39
|
+
rspec-support (3.8.0)
|
34
40
|
slop (3.6.0)
|
41
|
+
unf (0.1.4)
|
42
|
+
unf_ext
|
43
|
+
unf_ext (0.0.7.5)
|
44
|
+
user-agent-randomizer (0.2.0)
|
35
45
|
|
36
46
|
PLATFORMS
|
37
47
|
ruby
|
@@ -44,4 +54,4 @@ DEPENDENCIES
|
|
44
54
|
squash_matrix!
|
45
55
|
|
46
56
|
BUNDLED WITH
|
47
|
-
1.16.
|
57
|
+
1.16.2
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# SquashMatrix
|
2
2
|
|
3
|
-
|
3
|
+
Ruby SDK for www.squashmatrix.com
|
4
4
|
|
5
|
-
|
5
|
+
The generated client interacts with www.squashmatrix.com by retrieving player and club information and performing search requests.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -22,7 +22,94 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
|
25
|
+
```ruby
|
26
|
+
client = SquashMatrix::Client.new # initialize client
|
27
|
+
=> SquashMatrix::Client
|
28
|
+
client.player_info(42547) # retrieve player info for joshua wilkosz #42547
|
29
|
+
=> [
|
30
|
+
{
|
31
|
+
:event=>"2017 Melbourne Autumn State Open Pennant",
|
32
|
+
:division=>"State 2",
|
33
|
+
:round=>"7",
|
34
|
+
:position=>"3",
|
35
|
+
:games=>"2-3",
|
36
|
+
:points=>"67-73",
|
37
|
+
:rating_adjustment=>0.58,
|
38
|
+
:rating=>250.2,
|
39
|
+
:opponent_rating=>275.24,
|
40
|
+
:opponent_name=>"David Crossley",
|
41
|
+
:date=> Time,
|
42
|
+
:opponent_id=>26809,
|
43
|
+
:match_id=>1003302
|
44
|
+
}
|
45
|
+
]
|
46
|
+
client.club_info(336) # retrieve club info for melbourne university #336
|
47
|
+
=> {
|
48
|
+
:name=>"Melbourne University Squash Club",
|
49
|
+
:players=>[
|
50
|
+
{
|
51
|
+
:name=>"David Clegg",
|
52
|
+
:rating=>342.5,
|
53
|
+
:rank=>0,
|
54
|
+
:id=>43076
|
55
|
+
}
|
56
|
+
],
|
57
|
+
:juniors=>[
|
58
|
+
{
|
59
|
+
:name=>"Trevor Bryden",
|
60
|
+
:rating=>95.28,
|
61
|
+
:rank=>0,
|
62
|
+
:id=>72728
|
63
|
+
}
|
64
|
+
]
|
65
|
+
}
|
66
|
+
client.search("joshua") # search for 'joshua'
|
67
|
+
=> {
|
68
|
+
:players=>[
|
69
|
+
{
|
70
|
+
:name=>"Joshua Altmann",
|
71
|
+
:club_name=>"Monash University",
|
72
|
+
:id=>47508,
|
73
|
+
:rating=>107.821
|
74
|
+
}
|
75
|
+
],
|
76
|
+
:teams=>[
|
77
|
+
{
|
78
|
+
:name=>"Joshua mallison",
|
79
|
+
:division_name=>"Box 08",
|
80
|
+
:event_name=>"2017 Briars @ Thornleigh Box Challenge (Season 29)",
|
81
|
+
:id=>80792
|
82
|
+
}
|
83
|
+
],
|
84
|
+
:clubs=>[]
|
85
|
+
}
|
86
|
+
client.search("melbourne") # search for 'melbourne'
|
87
|
+
=> {
|
88
|
+
:players=>[
|
89
|
+
{
|
90
|
+
:name=>"Melbourne Simpson",
|
91
|
+
:club_name=>"Mirrabooka",
|
92
|
+
:id=>17797,
|
93
|
+
:rating=>199.607
|
94
|
+
}
|
95
|
+
],
|
96
|
+
:teams=>[
|
97
|
+
{
|
98
|
+
:name=>"Melbourne Uni (2)@Fitz",
|
99
|
+
:division_name=>"C Reserve",
|
100
|
+
:event_name=>"2012 Melbourne Spring SSL Women's Pennant",
|
101
|
+
:id=>39605
|
102
|
+
}
|
103
|
+
],
|
104
|
+
:clubs=>[
|
105
|
+
{
|
106
|
+
:name=>"Melbourne University",
|
107
|
+
:state=>"Victoria",
|
108
|
+
:id=>336
|
109
|
+
}
|
110
|
+
]
|
111
|
+
}
|
112
|
+
```
|
26
113
|
|
27
114
|
## Development
|
28
115
|
|
@@ -30,9 +117,11 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
30
117
|
|
31
118
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
119
|
|
120
|
+
To run tests, run `bundle exec rspec`
|
121
|
+
|
33
122
|
## Contributing
|
34
123
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
124
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/wilkosz/squash_matrix. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
36
125
|
|
37
126
|
## License
|
38
127
|
|
data/lib/squash_matrix/client.rb
CHANGED
@@ -1,47 +1,47 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
require 'date'
|
3
3
|
require 'timeout'
|
4
|
+
require 'http-cookie'
|
5
|
+
require 'user_agent_randomizer'
|
4
6
|
require_relative 'constants'
|
5
7
|
require_relative 'nokogiri-parser'
|
6
8
|
require_relative 'errors'
|
7
9
|
|
8
10
|
module SquashMatrix
|
9
11
|
|
10
|
-
# Client for
|
12
|
+
# Client for retrieving player and club information from squashmatrix.com.
|
11
13
|
# If authentication credentials are provided squash matrix will allow
|
12
14
|
# considerably more requests for an IP address and allow forbidden conent
|
13
15
|
# to be requested.
|
14
16
|
|
15
17
|
class Client
|
16
18
|
|
17
|
-
# Returns newly created Client
|
19
|
+
# Returns newly created Client
|
18
20
|
# @note If suppress_errors == false SquashMatrix::Errors::AuthorizationError will be raised if specified credentials are incorrect and squash matrix authentication returns forbidden
|
19
21
|
# @param [Hash] opts the options to create client
|
20
22
|
# @return [Client]
|
21
23
|
|
22
24
|
def initialize(player: nil, email: nil, password: nil, suppress_errors: false, timeout: 60)
|
25
|
+
@user_agent = UserAgentRandomizer::UserAgent.fetch(type: "desktop_browser").string
|
26
|
+
@squash_matrix_home_uri = URI::HTTP.build({ host: SquashMatrix::Constants::SQUASH_MATRIX_URL })
|
23
27
|
@suppress_errors = suppress_errors
|
24
28
|
@timeout = timeout
|
25
29
|
if ![player || email, password].any?(&:nil?)
|
26
|
-
@
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
cookie: nil,
|
31
|
-
player: player,
|
32
|
-
email: email,
|
33
|
-
password: password
|
34
|
-
}
|
30
|
+
@cookie_jar = HTTP::CookieJar.new()
|
31
|
+
@player = player
|
32
|
+
@email = email
|
33
|
+
@password = password
|
35
34
|
authenticate
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
39
|
-
# Returns club
|
38
|
+
# Returns club info.
|
40
39
|
# @note If suppress_errors == false SquashMatrix Errors will be raised upon HttpNotFound, HttpConflict, Timeout::Error, etc...
|
41
|
-
# @param id [
|
40
|
+
# @param id [Fixnum] club id found on squash matrix
|
42
41
|
# @return [Hash] hash object containing club information
|
43
42
|
|
44
43
|
def club_info(id=nil)
|
44
|
+
return if id.nil?
|
45
45
|
uri = URI::HTTP.build({
|
46
46
|
host: SquashMatrix::Constants::SQUASH_MATRIX_URL,
|
47
47
|
path: SquashMatrix::Constants::CLUB_PATH.gsub(':id', id.to_s)
|
@@ -50,9 +50,9 @@ module SquashMatrix
|
|
50
50
|
handle_http_request(uri, success_proc)
|
51
51
|
end
|
52
52
|
|
53
|
-
# Returns player
|
53
|
+
# Returns player info.
|
54
54
|
# @note If suppress_errors == false SquashMatrix Errors will be raised upon HttpNotFound, HttpConflict, Timeout::Error, etc...
|
55
|
-
# @param id [
|
55
|
+
# @param id [Fixnum] played id found on squash matrix
|
56
56
|
# @return [Hash] hash object containing player information
|
57
57
|
|
58
58
|
def player_info(id=nil)
|
@@ -78,8 +78,8 @@ module SquashMatrix
|
|
78
78
|
path: SquashMatrix::Constants::SEARCH_PATH})
|
79
79
|
query_params = {
|
80
80
|
Criteria: query,
|
81
|
-
SquashOnly:
|
82
|
-
RacquetballOnly:
|
81
|
+
SquashOnly: squash_only,
|
82
|
+
RacquetballOnly: racquetball_only}
|
83
83
|
success_proc = lambda {|res| SquashMatrix::NokogiriParser.search_results(res.body)}
|
84
84
|
handle_http_request(uri, success_proc,
|
85
85
|
{
|
@@ -96,15 +96,23 @@ module SquashMatrix
|
|
96
96
|
if is_get_request
|
97
97
|
req = Net::HTTP::Get.new(uri)
|
98
98
|
set_headers(req, headers: headers)
|
99
|
-
res = Net::HTTP.start(uri.hostname, uri.port) {|http| http.request(req)}
|
100
99
|
else
|
101
|
-
|
100
|
+
req = Net::HTTP::Post.new(uri)
|
101
|
+
set_headers(req)
|
102
|
+
form_data = []
|
103
|
+
query_params.each {|key, value| form_data.push([key.to_s, value.to_s])}
|
104
|
+
set_headers(req, headers: headers)
|
105
|
+
req.set_form(form_data, SquashMatrix::Constants::MULTIPART_FORM_DATA)
|
102
106
|
end
|
107
|
+
res = Net::HTTP.start(uri.hostname, uri.port, {use_ssl: uri.scheme == 'https'}) {|http| http.request(req)}
|
103
108
|
case res
|
104
|
-
when Net::HTTPSuccess
|
109
|
+
when Net::HTTPSuccess, Net::HTTPFound
|
105
110
|
return success_proc && success_proc.call(res) || res
|
106
111
|
when Net::HTTPConflict
|
107
|
-
|
112
|
+
unless @suppress_errors
|
113
|
+
raise SquashMatrix::Errors::ForbiddenError.new(res.body) if SquashMatrix::Constants::FORBIDDEN_ERROR_REGEX.match(res.body)
|
114
|
+
raise SquashMatrix::Errors::TooManyRequestsError.new(res.body) if SquashMatrix::Constants::TOO_MANY_REQUESTS_ERROR_REGEX.match(res.body)
|
115
|
+
end
|
108
116
|
else
|
109
117
|
raise SquashMatrix::Errors::UnknownError.new(res) unless @suppress_errors
|
110
118
|
end
|
@@ -115,32 +123,35 @@ module SquashMatrix
|
|
115
123
|
end
|
116
124
|
|
117
125
|
def authenticate
|
118
|
-
|
119
|
-
uri = URI::HTTP.build({
|
126
|
+
uri = URI::HTTPS.build({
|
120
127
|
host: SquashMatrix::Constants::SQUASH_MATRIX_URL,
|
121
128
|
path: SquashMatrix::Constants::LOGIN_PATH})
|
122
|
-
headers = {
|
123
|
-
SquashMatrix::Constants::CONTENT_TYPE_HEADER.to_sym => SquashMatrix::Constants::X_WWW__FROM_URL_ENCODED
|
124
|
-
}
|
125
129
|
query_params = {
|
126
|
-
UserName: @
|
127
|
-
Password: @
|
130
|
+
UserName: @player&.to_s || @email,
|
131
|
+
Password: @password,
|
128
132
|
RememberMe: false
|
129
133
|
}
|
134
|
+
headers = {
|
135
|
+
SquashMatrix::Constants::CONTENT_TYPE_HEADER => SquashMatrix::Constants::MULTIPART_FORM_DATA
|
136
|
+
}
|
137
|
+
# need to retrieve the asp.net session id
|
138
|
+
home_page_res = handle_http_request(@squash_matrix_home_uri, nil)
|
139
|
+
raise SquashMatrix::Errors::AuthorizationError.new(SquashMatrix::Constants::ERROR_RETRIEVING_ASPNET_SESSION) unless home_page_res
|
140
|
+
home_page_res[SquashMatrix::Constants::SET_COOKIE_HEADER].split('; ').each do |v|
|
141
|
+
@cookie_jar.parse(v, @squash_matrix_home_uri)
|
142
|
+
end
|
130
143
|
res = handle_http_request(uri, nil,
|
131
144
|
{
|
132
145
|
is_get_request: false,
|
133
146
|
query_params: query_params,
|
134
147
|
headers: headers
|
135
148
|
})
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
@authenticated[:player] = SquashMatrix::Constants::PLAYER_FROM_PATH_REGEX.match(res.response[SquashMatrix::Constants::LOCATION_HEADER])[1] if @authenticated[:email] && res.response[SquashMatrix::Constants::LOCATION_HEADER]
|
143
|
-
elsif !@suppress_errors
|
149
|
+
raise SquashMatrix::Errors::AuthorizationError.new(SquashMatrix::Constants::ERROR_RETRIEVING_ASPAUX_TOKEN) unless res
|
150
|
+
res[SquashMatrix::Constants::SET_COOKIE_HEADER].split('; ').each do |v|
|
151
|
+
@cookie_jar.parse(v, @squash_matrix_home_uri)
|
152
|
+
end
|
153
|
+
@player = SquashMatrix::Constants::PLAYER_FROM_PATH_REGEX.match(res[SquashMatrix::Constants::LOCATION_HEADER])[1] if @player.nil? && res[SquashMatrix::Constants::LOCATION_HEADER]
|
154
|
+
unless !@suppress_errors && @cookie_jar.cookies(@squash_matrix_home_uri).find {|c| c.name == SquashMatrix::Constants::ASPXAUTH_COOKIE_NAME && !c.value.empty?}
|
144
155
|
error_string = SquashMatrix::NokogiriParser.log_on_error(res.body).join(', ')
|
145
156
|
raise SquashMatrix::Errors::AuthorizationError.new(error_string)
|
146
157
|
end
|
@@ -148,19 +159,21 @@ module SquashMatrix
|
|
148
159
|
|
149
160
|
def set_headers(req=nil, headers: nil)
|
150
161
|
return unless req
|
151
|
-
headers_to_add = {
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
162
|
+
headers_to_add = {
|
163
|
+
SquashMatrix::Constants::USER_AGENT_HEADER => @user_agent,
|
164
|
+
SquashMatrix::Constants::HOST_HEADER => SquashMatrix::Constants::SQUASH_MATRIX_URL}
|
165
|
+
headers_to_add = headers_to_add.merge(headers) if headers
|
166
|
+
if @cookie_jar
|
167
|
+
cookies = @cookie_jar.cookies(@squash_matrix_home_uri).select do |c|
|
168
|
+
[
|
169
|
+
SquashMatrix::Constants::ASP_NET_SESSION_ID_COOKIE_NAME,
|
170
|
+
SquashMatrix::Constants::GROUP_ID_COOKIE_NAME,
|
171
|
+
SquashMatrix::Constants::ASPXAUTH_COOKIE_NAME
|
172
|
+
].include?(c.name)
|
173
|
+
end
|
174
|
+
headers_to_add = headers_to_add.merge({SquashMatrix::Constants::COOKIE_HEADER => HTTP::Cookie.cookie_value(cookies)})
|
175
|
+
end
|
176
|
+
headers_to_add.each {|key, val| req[key.to_s] = val}
|
164
177
|
end
|
165
178
|
end
|
166
179
|
end
|
@@ -8,17 +8,28 @@ module SquashMatrix
|
|
8
8
|
SEARCH_PATH = "/Home/Search"
|
9
9
|
PLAYER_RSULTS_QUERY = "max=0&X-Requested-With=XMLHttpRequest"
|
10
10
|
SET_COOKIE_HEADER = 'set-cookie'
|
11
|
+
COOKIE_HEADER = 'cookie'
|
11
12
|
LOCATION_HEADER = 'location'
|
12
13
|
X_WWW__FROM_URL_ENCODED = 'application/x-www-form-urlencoded'
|
13
14
|
MULTIPART_FORM_DATA = 'multipart/form-data'
|
14
|
-
CONTENT_TYPE_HEADER = '
|
15
|
+
CONTENT_TYPE_HEADER = 'content-type'
|
15
16
|
REFERER = "Home/Player/:id"
|
17
|
+
ASPXAUTH_COOKIE_NAME = ".ASPXAUTH"
|
18
|
+
ASP_NET_SESSION_ID_COOKIE_NAME = "ASP.NET_SessionId"
|
19
|
+
GROUP_ID_COOKIE_NAME = "GroupId"
|
20
|
+
HOST_HEADER = 'host'
|
21
|
+
USER_AGENT_HEADER = 'user-agent'
|
16
22
|
|
17
23
|
PLAYER_FROM_PATH_REGEX = /\/Home\/Player\/(.*)/
|
18
24
|
TEAM_FROM_PATH_REGEX = /\/Home\/Team\/(.*)/
|
19
25
|
CLUB_FROM_PATH_REGEX = /\/Home\/Club\/(.*)/
|
20
26
|
MATCH_FROM_PATH_REGEX = /\/Home\/Match\/(.*)/
|
21
27
|
CLUB_FROM_TITLE_REGEX = /Club - (.*)/
|
22
|
-
|
28
|
+
|
29
|
+
ERROR_RETRIEVING_ASPNET_SESSION = "Error retrieving ASP.NET_SessionId"
|
30
|
+
ERROR_RETRIEVING_ASPAUX_TOKEN = "Error retrieving .ASPXAUTH_TOKEN"
|
31
|
+
|
32
|
+
TOO_MANY_REQUESTS_ERROR_REGEX = /Request made too soon. This is to prevent abuse to the site. We apologise for the inconvenience/
|
33
|
+
FORBIDDEN_ERROR_REGEX = /Forbidden/
|
23
34
|
end
|
24
35
|
end
|
data/lib/squash_matrix/errors.rb
CHANGED
@@ -3,122 +3,129 @@ require_relative 'constants'
|
|
3
3
|
|
4
4
|
module SquashMatrix
|
5
5
|
class NokogiriParser
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
6
|
+
class << self
|
7
|
+
def player_info(body)
|
8
|
+
Nokogiri::HTML(body)&.xpath('//table[@id="results"]//tbody//tr')&.map do |r|
|
9
|
+
date = r.at_css('td[1]')&.content
|
10
|
+
opponent_id = r.at_css('td[10]//a')&.attribute('href')&.content
|
11
|
+
match_id = r.at_css('td[12]//a')&.attribute('href')&.content
|
12
|
+
rtn = {
|
13
|
+
event: r.at_css('td[2]')&.content,
|
14
|
+
division: r.at_css('td[3]')&.content,
|
15
|
+
round: r.at_css('td[4]')&.content,
|
16
|
+
position: r.at_css('td[5]')&.content,
|
17
|
+
games: r.at_css('td[6]')&.content,
|
18
|
+
points: r.at_css('td[7]')&.content,
|
19
|
+
rating_adjustment: r.at_css('td[8]')&.content&.to_f,
|
20
|
+
rating: r.at_css('td[9]')&.content&.to_f,
|
21
|
+
opponent_rating: r.at_css('td[11]')&.content&.to_f,
|
22
|
+
opponent_name: r.at_css('td[10]//a')&.content
|
23
|
+
}
|
24
|
+
rtn[:date] = Date.parse(date) if date
|
25
|
+
rtn[:opponent_id] = SquashMatrix::Constants::PLAYER_FROM_PATH_REGEX.match(opponent_id)[1].to_i if opponent_id
|
26
|
+
rtn[:match_id] = SquashMatrix::Constants::MATCH_FROM_PATH_REGEX.match(match_id)[1].to_i if match_id
|
27
|
+
rtn.values.any?(&:nil?) ? nil : rtn
|
28
|
+
end.compact
|
29
|
+
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
31
|
+
def club_info(body)
|
32
|
+
html = Nokogiri::HTML(body)
|
33
|
+
name = SquashMatrix::Constants::CLUB_FROM_TITLE_REGEX.match(html.css('title').text)[1]
|
34
|
+
players = html.xpath('//div[@id="Rankings"]//div[@class="columnmain"]//table[@class="alternaterows"]//tbody//tr')&.map do |r|
|
35
|
+
player_path = r.css('td[2]//a').attribute('href').value
|
36
|
+
rank = r.css('td[1]').text
|
37
|
+
rtn = {
|
38
|
+
name: r.css('td[2]').text,
|
39
|
+
rating: r.css('td[3]').text.to_f
|
40
|
+
}
|
41
|
+
rtn[:rank] = rank.to_i if rank
|
42
|
+
rtn[:id] = SquashMatrix::Constants::PLAYER_FROM_PATH_REGEX.match(player_path)[1].to_i if player_path
|
43
|
+
rtn
|
44
|
+
end.compact
|
45
|
+
juniors = html.xpath('//div[@id="Rankings"]//div[@class="columnside"]//table[@class="alternaterows"]//tbody//tr')&.map do |r|
|
46
|
+
player_path = r.css('td[2]//a').attribute('href').value
|
47
|
+
rank = r.css('td[1]').text
|
48
|
+
rtn = {
|
49
|
+
name: r.css('td[2]').text,
|
50
|
+
rating: r.css('td[3]').text.to_f
|
51
|
+
}
|
52
|
+
rtn[:rank] = rank.to_i if rank
|
53
|
+
rtn[:id] = SquashMatrix::Constants::PLAYER_FROM_PATH_REGEX.match(player_path)[1].to_i if player_path
|
54
|
+
rtn
|
55
|
+
end.compact
|
56
|
+
{
|
57
|
+
name: name,
|
58
|
+
players: players,
|
59
|
+
juniors: juniors
|
39
60
|
}
|
40
|
-
|
41
|
-
rtn[:id] = SquashMatrix::Constants::PLAYER_FROM_PATH_REGEX.match(player_path)[1] if player_path
|
42
|
-
rtn
|
43
|
-
end.compact
|
44
|
-
juniors = html.xpath('//div[@id="Rankings"]//div[@class="columnside"]//table[@class="alternaterows"]//tbody//tr')&.map do |r|
|
45
|
-
player_path = r.css('td[2]//a').attribute('href').value
|
46
|
-
rank = r.css('td[1]').text
|
47
|
-
rtn = {
|
48
|
-
name: r.css('td[2]').text,
|
49
|
-
rating: r.css('td[3]').text.to_f
|
50
|
-
}
|
51
|
-
rtn[:rank] = rank.to_i if rank
|
52
|
-
rtn[:id] = SquashMatrix::Constants::PLAYER_FROM_PATH_REGEX.match(player_path)[1] if player_path
|
53
|
-
rtn
|
54
|
-
end.compact
|
55
|
-
{
|
56
|
-
name: name,
|
57
|
-
players: players,
|
58
|
-
juniors: juniors
|
59
|
-
}
|
60
|
-
end
|
61
|
+
end
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
63
|
+
def search_results(body)
|
64
|
+
bc = Nokogiri::HTML.parse(body).at_xpath('//div[@id="bodycontent"]')&.children
|
65
|
+
return unless bc&.length
|
66
|
+
rtn = {}
|
67
|
+
bc&.each_with_index do |c, i|
|
68
|
+
if c.name == "h2"
|
69
|
+
case c.text
|
70
|
+
when "Players"
|
71
|
+
rtn[:players] = players_from_search(bc[i+2]) if bc[i+2].children.length
|
72
|
+
when "Teams"
|
73
|
+
rtn[:teams] = teams_from_search(bc[i+2]) if bc[i+2].children.length
|
74
|
+
when "Clubs"
|
75
|
+
rtn[:clubs] = clubs_from_search(bc[i+2]) if bc[i+2].children.length
|
76
|
+
end
|
75
77
|
end
|
76
78
|
end
|
79
|
+
rtn
|
77
80
|
end
|
78
|
-
rtn
|
79
|
-
end
|
80
81
|
|
81
|
-
|
82
|
-
|
83
|
-
|
82
|
+
def log_on_error(body)
|
83
|
+
Nokogiri::HTML(body)&.xpath('//div[@class="validation-summary-errors"]//ul//li')&.map(&:content)
|
84
|
+
end
|
84
85
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
86
|
+
private
|
87
|
+
|
88
|
+
def players_from_search(node)
|
89
|
+
node.css('tbody//tr')&.map do |tr|
|
90
|
+
id = tr.css('td[1]//a')&.attribute('href')&.value
|
91
|
+
rating = tr.css('td[3]')&.text
|
92
|
+
rtn = {
|
93
|
+
name: tr.css('td[1]')&.text,
|
94
|
+
club_name: tr.css('td[2]')&.text
|
95
|
+
}
|
96
|
+
rtn[:id] = SquashMatrix::Constants::PLAYER_FROM_PATH_REGEX.match(id)[1].to_i if id && !id.empty?
|
97
|
+
rtn[:rating] = rating.to_f if rating
|
98
|
+
rtn
|
99
|
+
end
|
96
100
|
end
|
97
|
-
end
|
98
101
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
102
|
+
def teams_from_search(node)
|
103
|
+
node.css('tbody//tr')&.map do |tr|
|
104
|
+
id = tr.css('td[1]//a')&.attribute('href')&.value
|
105
|
+
rtn = {
|
106
|
+
name: tr.css('td[1]')&.text,
|
107
|
+
division_name: tr.css('td[2]')&.text,
|
108
|
+
event_name: tr.css('td[3]')&.text
|
109
|
+
}
|
110
|
+
rtn[:id] = SquashMatrix::Constants::TEAM_FROM_PATH_REGEX.match(id)[1].to_i if id
|
111
|
+
rtn
|
112
|
+
end
|
109
113
|
end
|
110
|
-
end
|
111
114
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
115
|
+
def clubs_from_search(node)
|
116
|
+
node.css('tbody//tr')&.map do |tr|
|
117
|
+
id = tr.css('td[1]//a')&.attribute('href')&.value
|
118
|
+
rtn = {
|
119
|
+
name: tr.css('td[1]')&.text,
|
120
|
+
state: tr.css('td[2]')&.text
|
121
|
+
}
|
122
|
+
rtn[:id] = SquashMatrix::Constants::CLUB_FROM_PATH_REGEX.match(id)[1].to_i if id
|
123
|
+
rtn
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def requests_made_to_soon?(body)
|
128
|
+
Nokogiri::HTML(body)&.xpath('//body')
|
122
129
|
end
|
123
130
|
end
|
124
131
|
end
|
data/squash_matrix.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Joshua Wilkosz"]
|
10
10
|
spec.email = ["joshua@wilkosz.com.au"]
|
11
11
|
|
12
|
-
spec.summary = %q{
|
13
|
-
spec.description = %q{
|
12
|
+
spec.summary = %q{Ruby SDK for www.squashmatrix.com}
|
13
|
+
spec.description = %q{The generated client interacts with www.squashmatrix.com by retrieving player and club information and performing search requests}
|
14
14
|
spec.homepage = "https://github.com/wilkosz/squash_matrix"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -36,7 +36,8 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.add_development_dependency "rake", "~> 10.0"
|
37
37
|
spec.add_development_dependency "rspec", "~> 3.0"
|
38
38
|
spec.add_development_dependency "pry", "~> 0.10.3"
|
39
|
-
|
39
|
+
spec.add_runtime_dependency 'user-agent-randomizer', '~> 0.2'
|
40
|
+
spec.add_runtime_dependency 'http-cookie', '~> 1.0', '>= 1.0.3'
|
40
41
|
spec.add_runtime_dependency 'nokogiri', '~> 1.8', '>= 1.8.4'
|
41
42
|
spec.required_ruby_version = '>= 2.3.0'
|
42
43
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: squash_matrix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Wilkosz
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,6 +66,40 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.10.3
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: user-agent-randomizer
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.2'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.2'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: http-cookie
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.0'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 1.0.3
|
93
|
+
type: :runtime
|
94
|
+
prerelease: false
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '1.0'
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.0.3
|
69
103
|
- !ruby/object:Gem::Dependency
|
70
104
|
name: nokogiri
|
71
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,7 +120,8 @@ dependencies:
|
|
86
120
|
- - ">="
|
87
121
|
- !ruby/object:Gem::Version
|
88
122
|
version: 1.8.4
|
89
|
-
description:
|
123
|
+
description: The generated client interacts with www.squashmatrix.com by retrieving
|
124
|
+
player and club information and performing search requests
|
90
125
|
email:
|
91
126
|
- joshua@wilkosz.com.au
|
92
127
|
executables: []
|
@@ -132,8 +167,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
167
|
version: '0'
|
133
168
|
requirements: []
|
134
169
|
rubyforge_project:
|
135
|
-
rubygems_version: 2.6.
|
170
|
+
rubygems_version: 2.6.12
|
136
171
|
signing_key:
|
137
172
|
specification_version: 4
|
138
|
-
summary:
|
173
|
+
summary: Ruby SDK for www.squashmatrix.com
|
139
174
|
test_files: []
|