clashinator 0.2 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +7 -3
- data/README.md +27 -16
- data/Rakefile +9 -2
- data/clashinator.gemspec +6 -3
- data/config/secrets.sample.yml +1 -0
- data/lib/clashinator.rb +19 -9
- data/lib/clashinator/achievement.rb +16 -0
- data/lib/clashinator/army.rb +13 -0
- data/lib/clashinator/array_resource.rb +43 -0
- data/lib/clashinator/badge_url.rb +13 -0
- data/lib/clashinator/base.rb +94 -0
- data/lib/clashinator/clan.rb +64 -0
- data/lib/clashinator/clan_ranking.rb +8 -0
- data/lib/clashinator/client.rb +52 -63
- data/lib/clashinator/hero.rb +9 -0
- data/lib/clashinator/league.rb +65 -0
- data/lib/clashinator/location.rb +55 -0
- data/lib/clashinator/player.rb +17 -0
- data/lib/clashinator/player_ranking.rb +8 -0
- data/lib/clashinator/season.rb +11 -0
- data/lib/clashinator/spell.rb +9 -0
- data/lib/clashinator/troop.rb +9 -0
- data/lib/clashinator/util/camelcase.rb +8 -0
- data/lib/clashinator/util/underscore.rb +12 -0
- data/lib/clashinator/version.rb +1 -1
- data/lib/clashinator/warlog.rb +8 -0
- metadata +75 -14
- data/Gemfile.lock +0 -27
- data/lib/clashinator/exceptions.rb +0 -2
- data/lib/clashinator/exceptions/base.rb +0 -5
- data/lib/clashinator/exceptions/response_error.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed4851e0beea8740bebd70663cb2bbedf1a89ab8
|
4
|
+
data.tar.gz: a831cbf6903981ae591e0509d1dca692d0fa341c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bfbc1ab8d0057c15277dcd373580505d360df36db1914d9d28b66ebffa14b7b2ba75394b18aa6f1566f7dea50188430d2c0efbdc40f2d2a817a2bd7c7cf3d03
|
7
|
+
data.tar.gz: 2b840f99c50a0e4dbb403a6f12b7535ebe65d27586d4b484fcd550ecc06ff483d55711a8b2daae4968117f58033348e05772d49581a1823ce1d27ddd2cdf827a
|
data/.gitignore
CHANGED
@@ -28,9 +28,13 @@ build/
|
|
28
28
|
|
29
29
|
# for a library or gem, you might want to ignore these files since the code is
|
30
30
|
# intended to run in multiple environments; otherwise, check them in:
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
Gemfile.lock
|
32
|
+
.ruby-version
|
33
|
+
.ruby-gemset
|
34
34
|
|
35
35
|
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
36
36
|
.rvmrc
|
37
|
+
|
38
|
+
# hide secrets
|
39
|
+
secrets.yml
|
40
|
+
spec/fixtures/*.yml
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Clashinator
|
2
2
|
|
3
|
-
Ruby wrapper for the Clash of Clans API
|
3
|
+
Ruby wrapper for the Clash of Clans API, based on the v1 version
|
4
|
+
|
5
|
+
Note: These docs were updated for the new tagged version 1.0
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
@@ -27,32 +29,37 @@ With your access token, retrieve a client instance with it.
|
|
27
29
|
|
28
30
|
`client = Clashinator::Client.new('YOUR TOKEN')`
|
29
31
|
|
30
|
-
|
32
|
+
All query options can be passed as underscored variables instead of
|
33
|
+
camelcased, query options available are at: [https://developer.clashofclans.com](https://developer.clashofclans.com)
|
34
|
+
|
35
|
+
There are several types of objects you can retrieve:
|
31
36
|
|
32
37
|
```ruby
|
33
|
-
client.
|
38
|
+
clans = client.search_clans(name: 'vzlan warriors', min_members: 25)
|
39
|
+
|
40
|
+
clan = client.clan_info('#VQ2QUJG')
|
34
41
|
|
35
|
-
client.
|
42
|
+
players = client.list_clan_members('#VQ2QUJG')
|
36
43
|
|
37
|
-
client.
|
44
|
+
war_log = client.clan_war_log('#VQ2QUJG')
|
38
45
|
|
39
|
-
client.
|
46
|
+
locations = client.list_locations
|
40
47
|
|
41
|
-
client.
|
48
|
+
location = client.location_info(32000254)
|
42
49
|
|
43
|
-
client.
|
50
|
+
clan_rankings = client.location_clan_rankings(32000254)
|
44
51
|
|
45
|
-
client.
|
52
|
+
player_rankings = client.location_player_rankings(32000254)
|
46
53
|
|
47
|
-
client.
|
54
|
+
leagues = client.list_leagues
|
48
55
|
|
49
|
-
client.
|
56
|
+
league = client.league_info(29000022)
|
50
57
|
|
51
|
-
client.
|
58
|
+
seasons = client.league_seasons(29000022)
|
52
59
|
|
53
|
-
client.
|
60
|
+
player_rankings = client.league_season_rankings(29000022, '2015-10')
|
54
61
|
|
55
|
-
client.
|
62
|
+
player = client.player_info('#QOCRLV90')
|
56
63
|
```
|
57
64
|
|
58
65
|
## Development
|
@@ -61,10 +68,14 @@ After checking out the repo, run `bin/setup` to install dependencies. You can al
|
|
61
68
|
|
62
69
|
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).
|
63
70
|
|
64
|
-
|
71
|
+
Create a new file called `secrets.yml` in the config folder with the contents of `config/secrets.sample.yml`
|
72
|
+
Then, you'll need to generate an access token in Clash of Clans developer page at:
|
73
|
+
[https://developer.clashofclans.com](https://developer.clashofclans.com)
|
65
74
|
|
66
|
-
|
75
|
+
## Contributing
|
67
76
|
|
77
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/leocabeza/clash-api. 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.
|
78
|
+
Remember to add a test for each new feature you add, and before submitting a pull request, check that all tests are passing by running: `rake`
|
68
79
|
|
69
80
|
## License
|
70
81
|
|
data/Rakefile
CHANGED
data/clashinator.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["info@leonardocabeza.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{Ruby wrapper for the Clash of Clans API}
|
13
|
-
spec.homepage = "https://github.com/leocabeza/
|
13
|
+
spec.homepage = "https://github.com/leocabeza/clash-api"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
@@ -28,6 +28,9 @@ Gem::Specification.new do |spec|
|
|
28
28
|
|
29
29
|
spec.add_development_dependency "bundler", "~> 1.11"
|
30
30
|
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
-
spec.
|
32
|
-
spec.
|
31
|
+
spec.add_development_dependency "webmock", "~> 2.1", ">= 2.1.0"
|
32
|
+
spec.add_development_dependency "vcr", "~> 3.0", ">= 3.0.3"
|
33
|
+
spec.add_development_dependency "minitest", "~> 5.9", ">= 5.9.1"
|
34
|
+
|
35
|
+
spec.add_dependency "httparty", "~> 0.14.0"
|
33
36
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
token_test: 'PUT_TEST_TOKEN_HERE'
|
data/lib/clashinator.rb
CHANGED
@@ -1,10 +1,20 @@
|
|
1
|
-
require '
|
2
|
-
require 'faraday_middleware'
|
1
|
+
require 'httparty'
|
3
2
|
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
require 'clashinator/base.rb'
|
4
|
+
require 'clashinator/array_resource.rb'
|
5
|
+
require 'clashinator/army.rb'
|
6
|
+
require 'clashinator/season.rb'
|
7
|
+
require 'clashinator/clan_ranking.rb'
|
8
|
+
require 'clashinator/player_ranking.rb'
|
9
|
+
require 'clashinator/achievement.rb'
|
10
|
+
require 'clashinator/troop.rb'
|
11
|
+
require 'clashinator/hero.rb'
|
12
|
+
require 'clashinator/spell.rb'
|
13
|
+
require 'clashinator/warlog.rb'
|
14
|
+
require 'clashinator/badge_url.rb'
|
15
|
+
require 'clashinator/league.rb'
|
16
|
+
require 'clashinator/location.rb'
|
17
|
+
require 'clashinator/player.rb'
|
18
|
+
require 'clashinator/clan.rb'
|
19
|
+
require 'clashinator/version.rb'
|
20
|
+
require 'clashinator/client.rb'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Clashinator
|
2
|
+
# This class represents the achievement model
|
3
|
+
# through the player model
|
4
|
+
class Achievement
|
5
|
+
attr_accessor :name, :stars, :value, :target, :info, :completion_info
|
6
|
+
|
7
|
+
def initialize(attributes)
|
8
|
+
@name = attributes['name']
|
9
|
+
@stars = attributes['stars']
|
10
|
+
@value = attributes['value']
|
11
|
+
@target = attributes['target']
|
12
|
+
@info = attributes['info']
|
13
|
+
@completion_info = attributes['completion_info']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Clashinator
|
2
|
+
# This class represents the army model
|
3
|
+
# through the player model
|
4
|
+
class Army
|
5
|
+
attr_accessor :name, :level, :max_level
|
6
|
+
|
7
|
+
def initialize(attributes)
|
8
|
+
@name = attributes['name']
|
9
|
+
@level = attributes['level']
|
10
|
+
@max_level = attributes['maxLevel']
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Clashinator
|
2
|
+
# This class represents the array resource model
|
3
|
+
# This is only for array-based responses
|
4
|
+
# that contains an items attribute and
|
5
|
+
# a paging attribute
|
6
|
+
class ArrayResource
|
7
|
+
attr_accessor :items, :paging, :model
|
8
|
+
|
9
|
+
def initialize(model, items, paging = {})
|
10
|
+
# if after and before are equal, it means it's end of pagination
|
11
|
+
@model = model
|
12
|
+
@items = as_array_of_model(items)
|
13
|
+
@paging = Clashinator::ArrayResource::Cursor.new(
|
14
|
+
paging['cursors']['after'],
|
15
|
+
paging['cursors']['before']
|
16
|
+
) if paging.key?('cursors')
|
17
|
+
end
|
18
|
+
|
19
|
+
private def as_array_of_model(array)
|
20
|
+
new_array = []
|
21
|
+
|
22
|
+
array.each do |arr|
|
23
|
+
new_array.push(@model.new(arr)) if @model.class == Class
|
24
|
+
end
|
25
|
+
|
26
|
+
new_array
|
27
|
+
end
|
28
|
+
|
29
|
+
# This class represent the cursor model
|
30
|
+
# that contains an after & before attribute
|
31
|
+
# for properly paging array resources
|
32
|
+
class Cursor
|
33
|
+
attr_accessor :after, :before
|
34
|
+
|
35
|
+
def initialize(after, before)
|
36
|
+
# can't be both specified
|
37
|
+
# at the same time
|
38
|
+
@after = after
|
39
|
+
@before = before
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Clashinator
|
2
|
+
# This class represents the BadgeUrl model
|
3
|
+
class BadgeUrl
|
4
|
+
attr_accessor :tiny, :small, :medium, :large
|
5
|
+
|
6
|
+
def initialize(attributes)
|
7
|
+
@tiny = attributes['tiny']
|
8
|
+
@small = attributes['small']
|
9
|
+
@medium = attributes['medium']
|
10
|
+
@large = attributes['large']
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require_relative 'util/camelcase.rb'
|
2
|
+
require_relative 'util/underscore.rb'
|
3
|
+
|
4
|
+
module Clashinator
|
5
|
+
# This is the base class for the other entities
|
6
|
+
class Base
|
7
|
+
include HTTParty
|
8
|
+
include Underscorable
|
9
|
+
extend Camelizable
|
10
|
+
|
11
|
+
base_uri 'https://api.clashofclans.com'
|
12
|
+
|
13
|
+
CLASS_MAP = {
|
14
|
+
member_list: 'Player', achievements: 'Achievement',
|
15
|
+
troops: 'Troop', heroes: 'Hero', spells: 'Spell'
|
16
|
+
}.freeze
|
17
|
+
OBJECT_MAP = {
|
18
|
+
opponent: 'Clan', league: 'League',
|
19
|
+
location: 'Location', badge_urls: 'BadgeUrl',
|
20
|
+
icon_urls: 'BadgeUrl', clan: 'Clan'
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
def initialize(attrs)
|
24
|
+
attrs.each do |name, val|
|
25
|
+
lower_camel_cased = to_underscore(name)
|
26
|
+
(class << self; self; end).send(:attr_reader, lower_camel_cased.to_sym)
|
27
|
+
val = verify_hash_that_are_objects(lower_camel_cased.to_sym, val)
|
28
|
+
val = verify_array_of_classes(lower_camel_cased.to_sym, val)
|
29
|
+
instance_variable_set "@#{lower_camel_cased}", val
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def verify_hash_that_are_objects(lower_camel_cased, val)
|
34
|
+
if OBJECT_MAP.key? lower_camel_cased
|
35
|
+
class_name = 'Clashinator::' \
|
36
|
+
"#{OBJECT_MAP[lower_camel_cased]}"
|
37
|
+
val = Object
|
38
|
+
.const_get(class_name)
|
39
|
+
.new(val)
|
40
|
+
end
|
41
|
+
|
42
|
+
val
|
43
|
+
end
|
44
|
+
|
45
|
+
def verify_array_of_classes(lower_camel_cased, val)
|
46
|
+
key_found = CLASS_MAP.key?(lower_camel_cased)
|
47
|
+
val = get_array_resource(lower_camel_cased, val) if key_found
|
48
|
+
|
49
|
+
val
|
50
|
+
end
|
51
|
+
|
52
|
+
private def get_array_resource(lower_camel_cased, val)
|
53
|
+
class_name = "Clashinator::#{CLASS_MAP[lower_camel_cased]}"
|
54
|
+
model = Object.const_get(class_name)
|
55
|
+
# this condition is for paging structures
|
56
|
+
# for instance Clan.search_clans
|
57
|
+
if val.is_a? Array
|
58
|
+
val = Clashinator::ArrayResource.new(model, val)
|
59
|
+
# this other condition is for array based structures with no paging
|
60
|
+
# for instance member_list of Clan.clan_info 'member_list' attribute
|
61
|
+
elsif val.is_a?(Hash) && val.key?(:items) && val.key?(:paging)
|
62
|
+
val = Clashinator::ArrayResource.new(
|
63
|
+
model, val['items'], val['paging']
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
val
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.http_default_options(token)
|
71
|
+
{
|
72
|
+
headers: {
|
73
|
+
'Authorization' => "Bearer #{token}"
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.prepare_options(token, query_options = {})
|
79
|
+
# new hash to store camelcased attributes, to make it work
|
80
|
+
# with the official API
|
81
|
+
new_query_options = {}
|
82
|
+
query_options.each do |name, val|
|
83
|
+
name = to_camel_case(name.to_s)
|
84
|
+
val.gsub!('#', '%23') if val.class == String
|
85
|
+
new_query_options[name.to_sym] = val
|
86
|
+
end
|
87
|
+
|
88
|
+
# duplicate http_default_options to add new_query_options
|
89
|
+
http_default_options(token).dup.merge(query: new_query_options)
|
90
|
+
end
|
91
|
+
|
92
|
+
private_class_method :http_default_options
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Clashinator
|
2
|
+
# This class represents the clan model
|
3
|
+
class Clan < Base
|
4
|
+
def initialize(attrs)
|
5
|
+
super(attrs)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.clan_info(token, clan_tag)
|
9
|
+
clan_tag.gsub!('#', '%23')
|
10
|
+
new_options = prepare_options(token)
|
11
|
+
response = get(
|
12
|
+
"/v1/clans/#{clan_tag}",
|
13
|
+
new_options
|
14
|
+
)
|
15
|
+
|
16
|
+
return new(response.parsed_response) if response.ok?
|
17
|
+
raise response['reason'] unless response.ok?
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.search_clans(token, options)
|
21
|
+
new_options = prepare_options(token, options)
|
22
|
+
# TODO: options[:name] should be at least 3 chars long
|
23
|
+
response = get('/v1/clans', new_options)
|
24
|
+
|
25
|
+
if response.ok?
|
26
|
+
return Clashinator::ArrayResource.new(
|
27
|
+
Clashinator::Clan,
|
28
|
+
response.parsed_response['items'],
|
29
|
+
response.parsed_response['paging']
|
30
|
+
)
|
31
|
+
end
|
32
|
+
raise response['message'] unless response.ok?
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.list_clan_members(token, clan_tag, options = {})
|
36
|
+
new_options = prepare_options(token, options)
|
37
|
+
clan_tag.gsub!('#', '%23')
|
38
|
+
response = get("/v1/clans/#{clan_tag}/members", new_options)
|
39
|
+
|
40
|
+
if response.ok?
|
41
|
+
return Clashinator::ArrayResource.new(
|
42
|
+
Clashinator::Player, response.parsed_response['items'],
|
43
|
+
response.parsed_response['paging']
|
44
|
+
)
|
45
|
+
end
|
46
|
+
raise response['message'] unless response.ok?
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.clan_war_log(token, clan_tag, options = {})
|
50
|
+
# response.code will be 403 if clan war log is set to private
|
51
|
+
new_options = prepare_options(token, options)
|
52
|
+
clan_tag.gsub!('#', '%23')
|
53
|
+
response = get("/v1/clans/#{clan_tag}/warlog", new_options)
|
54
|
+
|
55
|
+
if response.ok?
|
56
|
+
return Clashinator::ArrayResource.new(
|
57
|
+
Clashinator::Warlog, response.parsed_response['items'],
|
58
|
+
response.parsed_response['paging']
|
59
|
+
)
|
60
|
+
end
|
61
|
+
raise response['reason'] unless response.ok?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/clashinator/client.rb
CHANGED
@@ -1,89 +1,78 @@
|
|
1
1
|
module Clashinator
|
2
|
+
# Client class that acts as
|
3
|
+
# interface of http methods
|
4
|
+
# available for the client itself
|
2
5
|
class Client
|
3
|
-
CLASH_OF_CLANS_API = 'https://api.clashofclans.com'
|
4
|
-
ENDPOINTS = {
|
5
|
-
find_clan: '/v1/clans',
|
6
|
-
get_clan_info: '/v1/clans/{clan_tag}',
|
7
|
-
list_clan_members: '/v1/clans/{clan_tag}/members',
|
8
|
-
list_war_log: '/v1/clans/{clan_tag}/warlog',
|
9
|
-
list_locations: '/v1/locations',
|
10
|
-
get_location_info: '/v1/locations/{location_id}',
|
11
|
-
get_clan_ranking_for_location: '/v1/locations/{location_id}/rankings/clans',
|
12
|
-
get_player_ranking_for_location: '/v1/locations/{location_id}/rankings/players',
|
13
|
-
list_leagues: '/v1/leagues',
|
14
|
-
get_league: '/v1/leagues/{league_id}',
|
15
|
-
get_league_seasons: '/v1/leagues/{league_id}/seasons',
|
16
|
-
get_league_season_rankings: '/v1/leagues/{league_id}/seasons/{season_id}'
|
17
|
-
}
|
18
|
-
|
19
6
|
attr_reader :token
|
20
7
|
|
21
8
|
def initialize(token)
|
22
9
|
@token = token
|
23
10
|
end
|
24
11
|
|
25
|
-
|
26
|
-
|
12
|
+
# client class methods
|
13
|
+
|
14
|
+
def search_clans(options)
|
15
|
+
Clashinator::Clan.search_clans(@token, options)
|
27
16
|
end
|
28
17
|
|
29
|
-
def
|
30
|
-
|
18
|
+
def clan_info(tag)
|
19
|
+
Clashinator::Clan.clan_info(@token, tag)
|
20
|
+
end
|
21
|
+
|
22
|
+
def list_clan_members(tag, options = {})
|
23
|
+
Clashinator::Clan.list_clan_members(@token, tag, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def clan_war_log(tag, options = {})
|
27
|
+
Clashinator::Clan.clan_war_log(@token, tag, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
# location class methods
|
31
|
+
|
32
|
+
def list_locations(options = {})
|
33
|
+
Clashinator::Location.list_locations(@token, options)
|
31
34
|
end
|
32
35
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
def location_info(location_id)
|
37
|
+
Clashinator::Location.location_info(@token, location_id)
|
38
|
+
end
|
39
|
+
|
40
|
+
def location_clan_rankings(location_id, options = {})
|
41
|
+
Clashinator::Locaton.location_clan_rankings(
|
42
|
+
@token, location_id, options
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def location_player_rankings(player_tag, options = {})
|
47
|
+
Clashinator::Location.location_player_rankings(
|
48
|
+
@token, player_tag, options
|
38
49
|
)
|
39
|
-
if response.success?
|
40
|
-
JSON.parse(response.body.to_json)
|
41
|
-
else
|
42
|
-
raise Exceptions::ResponseError.new(response),
|
43
|
-
'Clash of clans API has returned the error.'
|
44
|
-
end
|
45
50
|
end
|
46
51
|
|
47
|
-
|
48
|
-
|
49
|
-
def
|
50
|
-
|
51
|
-
query_params = ''
|
52
|
-
if has_path_param(url)
|
53
|
-
params.each do |key, value|
|
54
|
-
url.gsub!("{#{key}}", CGI::escape(value.to_s))
|
55
|
-
end
|
56
|
-
url.gsub!(/\/{\w+}/, '')
|
57
|
-
else
|
58
|
-
query_params = params
|
59
|
-
end
|
60
|
-
{url: url, query_params: query_params}
|
52
|
+
# league class methods
|
53
|
+
|
54
|
+
def list_leagues(options = {})
|
55
|
+
Clashinator::League.list_leagues(@token, options)
|
61
56
|
end
|
62
57
|
|
63
|
-
def
|
64
|
-
|
58
|
+
def league_info(league_id)
|
59
|
+
Clashinator::League.league_info(@token, league_id)
|
65
60
|
end
|
66
61
|
|
67
|
-
def
|
68
|
-
|
69
|
-
!has_path_param.nil?
|
62
|
+
def league_seasons(league_id, options = {})
|
63
|
+
Clashinator::League.league_seasons(@token, league_id, options)
|
70
64
|
end
|
71
65
|
|
72
|
-
def
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
66
|
+
def league_season_rankings(league_id, season_id, options = {})
|
67
|
+
Clashinator::League.league_season_rankings(
|
68
|
+
@token, league_id, season_id, options
|
69
|
+
)
|
77
70
|
end
|
78
71
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
content_type: 'application/json',
|
84
|
-
authorization: "Bearer #{token}"
|
85
|
-
}
|
86
|
-
}
|
72
|
+
# player class methods
|
73
|
+
|
74
|
+
def player_info(tag)
|
75
|
+
Clashinator::Player.player_info(@token, tag)
|
87
76
|
end
|
88
77
|
end
|
89
78
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Clashinator
|
2
|
+
# This class represents the league model
|
3
|
+
class League < Base
|
4
|
+
def initialize(attrs)
|
5
|
+
super(attrs)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.list_leagues(token, options = {})
|
9
|
+
new_options = prepare_options(token, options)
|
10
|
+
response = get('/v1/leagues', new_options)
|
11
|
+
|
12
|
+
if response.ok?
|
13
|
+
return Clashinator::ArrayResource.new(
|
14
|
+
Clashinator::League, response.parsed_response['items'],
|
15
|
+
response.parsed_response['paging']
|
16
|
+
)
|
17
|
+
end
|
18
|
+
raise response['message'] unless response.ok?
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.league_info(token, league_id)
|
22
|
+
new_options = prepare_options(token)
|
23
|
+
response = get("/v1/leagues/#{league_id}", new_options)
|
24
|
+
|
25
|
+
return new(response.parsed_response) if response.ok?
|
26
|
+
raise response['message'] unless response.ok?
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.league_seasons(token, league_id, options = {})
|
30
|
+
new_options = prepare_options(token, options)
|
31
|
+
response = get("/v1/leagues/#{league_id}/seasons", new_options)
|
32
|
+
|
33
|
+
if response.ok?
|
34
|
+
return Clashinator::ArrayResource.new(
|
35
|
+
Clashinator::Season, response.parsed_response['items'],
|
36
|
+
response.parsed_response['paging']
|
37
|
+
)
|
38
|
+
end
|
39
|
+
raise response['reason'] unless response.ok?
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.league_season_rankings(token, league_id, season_id, options = {})
|
43
|
+
# only available for legend_league
|
44
|
+
response = prepare_response_season_rankings(
|
45
|
+
league_id, season_id, token, options
|
46
|
+
)
|
47
|
+
if response.ok?
|
48
|
+
return Clashinator::ArrayResource.new(
|
49
|
+
Clashinator::PlayerRanking, response.parsed_response['items'],
|
50
|
+
response.parsed_response['paging']
|
51
|
+
)
|
52
|
+
end
|
53
|
+
raise response['reason'] unless response.ok?
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.prepare_response_season_rankings(league_id, season_id, token, options)
|
57
|
+
get(
|
58
|
+
"/v1/leagues/#{league_id}/seasons/#{season_id}",
|
59
|
+
prepare_options(token, options)
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
private_class_method :prepare_response_season_rankings
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Clashinator
|
2
|
+
# This class represents the location model
|
3
|
+
class Location < Base
|
4
|
+
def initialize(attrs)
|
5
|
+
super(attrs)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.list_locations(token, options = {})
|
9
|
+
new_options = prepare_options(token, options)
|
10
|
+
response = get('/v1/locations', new_options)
|
11
|
+
|
12
|
+
if response.ok?
|
13
|
+
return Clashinator::ArrayResource.new(
|
14
|
+
Clashinator::Location, response.parsed_response['items'],
|
15
|
+
response.parsed_response['paging']
|
16
|
+
)
|
17
|
+
end
|
18
|
+
raise response['message'] unless response.ok?
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.location_info(token, location_id)
|
22
|
+
new_options = prepare_options(token)
|
23
|
+
response = get("/v1/locations/#{location_id}", new_options)
|
24
|
+
|
25
|
+
return new(response.parsed_response) if response.ok?
|
26
|
+
raise response['message'] unless response.ok?
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.location_clan_rankings(token, location_id, options = {})
|
30
|
+
new_options = prepare_options(token, options)
|
31
|
+
response = get("/v1/locations/#{location_id}/rankings/clans", new_options)
|
32
|
+
|
33
|
+
if response.ok?
|
34
|
+
return Clashinator::ArrayResource.new(
|
35
|
+
Clashinator::ClanRanking, response.parsed_response['items'],
|
36
|
+
response.parsed_response['paging']
|
37
|
+
)
|
38
|
+
end
|
39
|
+
raise response['reason'] unless response.ok?
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.location_player_rankings(token, location_id, options = {})
|
43
|
+
response = get(
|
44
|
+
"/v1/locations/#{location_id}/rankings/players",
|
45
|
+
prepare_options(token, options)
|
46
|
+
)
|
47
|
+
|
48
|
+
return Clashinator::ArrayResource.new(
|
49
|
+
Clashinator::PlayerRanking, response.parsed_response['items'],
|
50
|
+
response.parsed_response['paging']
|
51
|
+
) if response.ok?
|
52
|
+
raise response['reason'] unless response.ok?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Clashinator
|
2
|
+
# This class represents the player model
|
3
|
+
class Player < Base
|
4
|
+
def initialize(attrs)
|
5
|
+
super(attrs)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.player_info(token, player_tag)
|
9
|
+
player_tag.gsub!('#', '%23')
|
10
|
+
new_options = prepare_options(token)
|
11
|
+
response = get("/v1/players/#{player_tag}", new_options)
|
12
|
+
|
13
|
+
return new(response.parsed_response) if response.ok?
|
14
|
+
raise response['reason'] unless response.ok?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# module to convert camelcase to underscore
|
2
|
+
module Underscorable
|
3
|
+
def to_underscore(name)
|
4
|
+
modified_word = name.dup
|
5
|
+
modified_word.gsub!(/::/, '/')
|
6
|
+
modified_word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
7
|
+
modified_word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
8
|
+
modified_word.tr!('-', '_')
|
9
|
+
modified_word.downcase!
|
10
|
+
modified_word
|
11
|
+
end
|
12
|
+
end
|
data/lib/clashinator/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clashinator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0
|
4
|
+
version: '1.0'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leonardo Cabeza
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,33 +39,79 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: webmock
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
48
|
-
|
47
|
+
version: '2.1'
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 2.1.0
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '2.1'
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 2.1.0
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: vcr
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.0'
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 3.0.3
|
71
|
+
type: :development
|
49
72
|
prerelease: false
|
50
73
|
version_requirements: !ruby/object:Gem::Requirement
|
51
74
|
requirements:
|
52
75
|
- - "~>"
|
53
76
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0
|
77
|
+
version: '3.0'
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 3.0.3
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: minitest
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '5.9'
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 5.9.1
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '5.9'
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 5.9.1
|
55
101
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
102
|
+
name: httparty
|
57
103
|
requirement: !ruby/object:Gem::Requirement
|
58
104
|
requirements:
|
59
105
|
- - "~>"
|
60
106
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
107
|
+
version: 0.14.0
|
62
108
|
type: :runtime
|
63
109
|
prerelease: false
|
64
110
|
version_requirements: !ruby/object:Gem::Requirement
|
65
111
|
requirements:
|
66
112
|
- - "~>"
|
67
113
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
114
|
+
version: 0.14.0
|
69
115
|
description:
|
70
116
|
email:
|
71
117
|
- info@leonardocabeza.com
|
@@ -76,7 +122,6 @@ files:
|
|
76
122
|
- ".gitignore"
|
77
123
|
- CODE_OF_CONDUCT.md
|
78
124
|
- Gemfile
|
79
|
-
- Gemfile.lock
|
80
125
|
- LICENSE
|
81
126
|
- LICENSE.txt
|
82
127
|
- README.md
|
@@ -84,13 +129,29 @@ files:
|
|
84
129
|
- bin/console
|
85
130
|
- bin/setup
|
86
131
|
- clashinator.gemspec
|
132
|
+
- config/secrets.sample.yml
|
87
133
|
- lib/clashinator.rb
|
134
|
+
- lib/clashinator/achievement.rb
|
135
|
+
- lib/clashinator/army.rb
|
136
|
+
- lib/clashinator/array_resource.rb
|
137
|
+
- lib/clashinator/badge_url.rb
|
138
|
+
- lib/clashinator/base.rb
|
139
|
+
- lib/clashinator/clan.rb
|
140
|
+
- lib/clashinator/clan_ranking.rb
|
88
141
|
- lib/clashinator/client.rb
|
89
|
-
- lib/clashinator/
|
90
|
-
- lib/clashinator/
|
91
|
-
- lib/clashinator/
|
142
|
+
- lib/clashinator/hero.rb
|
143
|
+
- lib/clashinator/league.rb
|
144
|
+
- lib/clashinator/location.rb
|
145
|
+
- lib/clashinator/player.rb
|
146
|
+
- lib/clashinator/player_ranking.rb
|
147
|
+
- lib/clashinator/season.rb
|
148
|
+
- lib/clashinator/spell.rb
|
149
|
+
- lib/clashinator/troop.rb
|
150
|
+
- lib/clashinator/util/camelcase.rb
|
151
|
+
- lib/clashinator/util/underscore.rb
|
92
152
|
- lib/clashinator/version.rb
|
93
|
-
|
153
|
+
- lib/clashinator/warlog.rb
|
154
|
+
homepage: https://github.com/leocabeza/clash-api
|
94
155
|
licenses:
|
95
156
|
- MIT
|
96
157
|
metadata:
|
data/Gemfile.lock
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
clashinator (0.1.2)
|
5
|
-
faraday (~> 0.9.2)
|
6
|
-
faraday_middleware (~> 0.10)
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
faraday (0.9.2)
|
12
|
-
multipart-post (>= 1.2, < 3)
|
13
|
-
faraday_middleware (0.10.0)
|
14
|
-
faraday (>= 0.7.4, < 0.10)
|
15
|
-
multipart-post (2.0.0)
|
16
|
-
rake (10.5.0)
|
17
|
-
|
18
|
-
PLATFORMS
|
19
|
-
ruby
|
20
|
-
|
21
|
-
DEPENDENCIES
|
22
|
-
bundler (~> 1.11)
|
23
|
-
clashinator!
|
24
|
-
rake (~> 10.0)
|
25
|
-
|
26
|
-
BUNDLED WITH
|
27
|
-
1.11.2
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module Clashinator
|
2
|
-
module Exceptions
|
3
|
-
class ResponseError < Base
|
4
|
-
attr_reader :response
|
5
|
-
|
6
|
-
def initialize(response)
|
7
|
-
@response = response
|
8
|
-
end
|
9
|
-
|
10
|
-
def to_s
|
11
|
-
super +
|
12
|
-
format(' (%s)', data.map { |k, v| %(#{k}: "#{v}") }.join(', '))
|
13
|
-
end
|
14
|
-
|
15
|
-
def error_code
|
16
|
-
data[:error_code] || data['error_code']
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def data
|
22
|
-
@data ||= begin
|
23
|
-
JSON.parse(response.body)
|
24
|
-
rescue JSON::ParserError
|
25
|
-
{ error_code: response.status, reason: response.body.reason }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|