clash_of_clans_api 0.2.0 → 0.4.0
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/README.adoc +39 -7
- data/lib/clash_of_clans_api/api.rb +39 -33
- data/lib/clash_of_clans_api/client.rb +27 -14
- data/lib/clash_of_clans_api/models/base.rb +35 -29
- data/lib/clash_of_clans_api/models/builder_base_league.rb +10 -0
- data/lib/clash_of_clans_api/models/capital_league.rb +10 -0
- data/lib/clash_of_clans_api/models/chat_language.rb +11 -0
- data/lib/clash_of_clans_api/models/clan.rb +32 -22
- data/lib/clash_of_clans_api/models/clan_capital.rb +11 -0
- data/lib/clash_of_clans_api/models/clan_capital_district.rb +11 -0
- data/lib/clash_of_clans_api/models/clan_location.rb +11 -0
- data/lib/clash_of_clans_api/models/hero.rb +2 -0
- data/lib/clash_of_clans_api/models/hero_equipment.rb +12 -0
- data/lib/clash_of_clans_api/models/paginated_response.rb +3 -2
- data/lib/clash_of_clans_api/models/pagination_cursors.rb +10 -0
- data/lib/clash_of_clans_api/models/pagination_paging.rb +10 -0
- data/lib/clash_of_clans_api/models/player.rb +35 -28
- data/lib/clash_of_clans_api/models/player_house.rb +10 -0
- data/lib/clash_of_clans_api/models/player_house_element.rb +10 -0
- data/lib/clash_of_clans_api/models/war.rb +18 -0
- data/lib/clash_of_clans_api/models/war_attack.rb +14 -0
- data/lib/clash_of_clans_api/models/war_clan.rb +19 -0
- data/lib/clash_of_clans_api/models/war_clan_member.rb +16 -0
- data/lib/clash_of_clans_api/models/war_league.rb +10 -0
- data/lib/clash_of_clans_api/token_api.rb +2 -2
- data/lib/clash_of_clans_api/token_client.rb +15 -1
- data/lib/clash_of_clans_api/utils.rb +0 -25
- data/lib/clash_of_clans_api/version.rb +1 -1
- metadata +35 -7
- data/lib/clash_of_clans_api/endpoint_methods.rb +0 -67
- data/lib/clash_of_clans_api/no_success_error.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3406e2ce3f3bf897da83e7a6412a66e692bb76e8df66b83d84a7b3132663af2
|
4
|
+
data.tar.gz: 56b4c3b5d2bcd0fd39dcc80a44182e783c24087442fed953e5f85ab8e221b9f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 451953dbac8d17669134d8cd072425e1f406aa50425b01fc003549a1285337cae130f60831f3294546128cbd717f97255ed0c82372982729f44eeebe0c962d4c
|
7
|
+
data.tar.gz: f098a36f13f7925fc402e38517115610a7e686c1ec431bf60bef177b9acf27dee139b839a88ec898dfac4de6af484c86e9f815b717b5fd71a021838b0c38ddcb
|
data/README.adoc
CHANGED
@@ -28,12 +28,12 @@ $ gem install clash_of_clans_api
|
|
28
28
|
|
29
29
|
==== API Communication
|
30
30
|
|
31
|
-
To communicate with the Clash of Clans API, an API
|
32
|
-
|
31
|
+
To communicate with the Clash of Clans API, an API key is required.
|
32
|
+
If you like to use the library to create and manage API keys, see <<Token API>>.
|
33
33
|
|
34
34
|
The gem provides two classes for communication.
|
35
35
|
`ClashOfClansApi::Api` is a low-level interface that implements methods for all API endpoints.
|
36
|
-
If the request is successful, the API’s JSON response is parsed and returned, otherwise
|
36
|
+
If the request is successful, the API’s JSON response is parsed and returned, otherwise an `ApiFrame::NoSuccessError` is raised.
|
37
37
|
`ClashOfClansApi::Client` is a higher-level interface that exposes its `ClashOfClansApi::Api` instance through `ClashOfClansApi::Client#api`.
|
38
38
|
Both classes’ initializers take a single argument, the API token.
|
39
39
|
|
@@ -44,20 +44,52 @@ They are derived from the https://developer.clashofclans.com/#/documentation[API
|
|
44
44
|
. Replace slashes (`/`) with underscores (`\_`) and keep only inner ones (`clans_{clanTag}_currentwar_leaguegroup`).
|
45
45
|
. In case of path arguments, singularize the path segment referenced by the argument (`clan_{clanTag}_currentwar_leaguegroup`).
|
46
46
|
. Remove path argument segments (`clan_currentwar_leaguegroup`).
|
47
|
+
. Remove any hyphens.
|
47
48
|
|
48
49
|
Path arguments are converted to positional arguments in the order of definition in the original path name.
|
49
50
|
Path arguments will automatically be URL-escaped.
|
50
51
|
A URL query in the form of a `Hash` can be passed as the named parameter `query:`.
|
51
52
|
|
53
|
+
==== Token API
|
54
|
+
|
55
|
+
Creating, listing and deleting API keys (tokens) is supported in `ClashOfClansApi::TokenClient` using the email address and password from the Clash of Clans Developer website.
|
56
|
+
|
57
|
+
[source,ruby]
|
58
|
+
----
|
59
|
+
token_client = ClashOfClansApi::TokenClient.new(email, password)
|
60
|
+
token_client.login!
|
61
|
+
|
62
|
+
# Return a list of the currently registered API keys.
|
63
|
+
token_client.list_api_keys
|
64
|
+
|
65
|
+
# Create a new API key for the IP address 127.0.0.1 and create a ClashOfClansApi::Client from it.
|
66
|
+
token = token_client.create_api_key('my_key_name', 'This is a description for my API key.', ['127.0.0.1'])
|
67
|
+
client = token.client_from_token
|
68
|
+
|
69
|
+
# Create or get an API key with the given name for the current IPv4 address.
|
70
|
+
other_token = token_client.create_or_get_api_key_for_current_ipv4_address('test_key_name', overwrite: true)
|
71
|
+
|
72
|
+
# Revoke the previously generated tokens.
|
73
|
+
token_client.revoke_api_key(token.id)
|
74
|
+
other_token.revoke
|
75
|
+
|
76
|
+
# Logging out is not required, but possible.
|
77
|
+
token_client.logout
|
78
|
+
----
|
79
|
+
|
80
|
+
This feature can be useful for applications whose host changes their IP address without human interaction as well as for large (federated) applications with too many requests for a single or a few manually created tokens.
|
81
|
+
|
82
|
+
Similar to `ClashOfClansApi::Api` and `ClashOfClansApi::Client`, there is also a lower-level implementation of the token API in `ClashOfClansApi::TokenApi`.
|
83
|
+
However, its usage is not recommended.
|
84
|
+
|
52
85
|
==== Clan and player tags
|
53
86
|
|
54
87
|
Tags in Clash of Clans are subject to format restrictions.
|
55
88
|
Since those restrictions are well known, `ClashOfClansApi::Tags` provides class methods for checking the format (`.sanitizable?`) and sanitizing ill-formatted tags up to a certain degree (`.sanitize`).
|
56
89
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
Therefore, those mistakes should be catched before sending a request.
|
90
|
+
Since the beginning of 2022, the API consistently corrects the letter `O` in requests to the number `0`, which was not the case before.
|
91
|
+
Previously, this could lead to multiple database entries for the same player, which the `.sanitize` method could prevent.
|
92
|
+
While this isn’t a problem anymore in this specific use case, it might come in handy for querying user input in ones own database.
|
61
93
|
|
62
94
|
|
63
95
|
=== Development
|
@@ -1,10 +1,10 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'api_frame'
|
2
|
+
|
3
3
|
require_relative 'utils'
|
4
4
|
|
5
5
|
module ClashOfClansApi
|
6
6
|
class Api
|
7
|
-
include EndpointMethods
|
7
|
+
include ApiFrame::EndpointMethods
|
8
8
|
|
9
9
|
BASE_URI = URI('https://api.clashofclans.com/v1/')
|
10
10
|
|
@@ -18,40 +18,46 @@ module ClashOfClansApi
|
|
18
18
|
@api_token = api_token
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def default_headers
|
22
22
|
{
|
23
23
|
'Authorization' => "Bearer #{api_token}",
|
24
24
|
}
|
25
25
|
end
|
26
26
|
|
27
|
-
define_endpoint :clan_currentwar_leaguegroup,
|
28
|
-
define_endpoint :clanwarleagues_war,
|
29
|
-
define_endpoint :clan_warlog,
|
30
|
-
define_endpoint :clans,
|
31
|
-
define_endpoint :clan_currentwar,
|
32
|
-
define_endpoint :clan,
|
33
|
-
define_endpoint :clan_members,
|
34
|
-
|
35
|
-
|
36
|
-
define_endpoint :
|
37
|
-
|
38
|
-
|
39
|
-
define_endpoint :
|
40
|
-
define_endpoint :
|
41
|
-
define_endpoint :
|
42
|
-
define_endpoint :
|
43
|
-
define_endpoint :
|
44
|
-
|
45
|
-
define_endpoint :
|
46
|
-
define_endpoint :
|
47
|
-
define_endpoint :
|
48
|
-
define_endpoint :
|
49
|
-
|
50
|
-
define_endpoint :
|
51
|
-
|
52
|
-
define_endpoint :
|
53
|
-
|
54
|
-
define_endpoint :
|
55
|
-
define_endpoint :
|
27
|
+
define_endpoint :clan_currentwar_leaguegroup, method: :get, endpoint: proc { |clan_tag| "clans/#{ApiFrame::Utils.url_escape(clan_tag)}/currentwar/leaguegroup" }
|
28
|
+
define_endpoint :clanwarleagues_war, method: :get, endpoint: proc { | war_tag| "clanwarleagues/wars/#{ApiFrame::Utils.url_escape(war_tag)}" }
|
29
|
+
define_endpoint :clan_warlog, method: :get, endpoint: proc { |clan_tag| "clans/#{ApiFrame::Utils.url_escape(clan_tag)}/warlog" }
|
30
|
+
define_endpoint :clans, method: :get, endpoint: 'clans'
|
31
|
+
define_endpoint :clan_currentwar, method: :get, endpoint: proc { |clan_tag| "clans/#{ApiFrame::Utils.url_escape(clan_tag)}/currentwar" }
|
32
|
+
define_endpoint :clan, method: :get, endpoint: proc { |clan_tag| "clans/#{ApiFrame::Utils.url_escape(clan_tag)}" }
|
33
|
+
define_endpoint :clan_members, method: :get, endpoint: proc { |clan_tag| "clans/#{ApiFrame::Utils.url_escape(clan_tag)}/members" }
|
34
|
+
define_endpoint :clan_capitalraidseasons, method: :get, endpoint: proc { |clan_tag| "clans/#{ApiFrame::Utils.url_escape(clan_tag)}/capitalraidseasons" }
|
35
|
+
|
36
|
+
define_endpoint :player, method: :get, endpoint: proc { |player_tag| "players/#{ApiFrame::Utils.url_escape(player_tag)}" }
|
37
|
+
define_endpoint :player_verifytoken, method: :post, endpoint: proc { |player_tag| "players/#{ApiFrame::Utils.url_escape(player_tag)}/verifytoken" }, body: proc { |token:| %Q({"token":"#{token}"}) }
|
38
|
+
|
39
|
+
define_endpoint :capitalleagues, method: :get, endpoint: 'capitalleagues'
|
40
|
+
define_endpoint :leagues, method: :get, endpoint: 'leagues'
|
41
|
+
define_endpoint :league_season, method: :get, endpoint: proc { | league_id, season_id | "leagues/#{ApiFrame::Utils.url_escape( league_id)}/seasons/#{ApiFrame::Utils.url_escape(season_id)}" }
|
42
|
+
define_endpoint :capitalleague, method: :get, endpoint: proc { | capitalleague_id | "capitalleagues/#{ApiFrame::Utils.url_escape( capitalleague_id)}" }
|
43
|
+
define_endpoint :builderbaseleague, method: :get, endpoint: proc { |builderbaseleague_id | "builderbaseleagues/#{ApiFrame::Utils.url_escape(builderbaseleague_id)}" }
|
44
|
+
define_endpoint :builderbaseleagues, method: :get, endpoint: 'builderbaseleagues'
|
45
|
+
define_endpoint :league, method: :get, endpoint: proc { | league_id | "leagues/#{ApiFrame::Utils.url_escape( league_id)}" }
|
46
|
+
define_endpoint :league_seasons, method: :get, endpoint: proc { | league_id | "leagues/#{ApiFrame::Utils.url_escape( league_id)}/seasons" }
|
47
|
+
define_endpoint :warleague, method: :get, endpoint: proc { | warleague_id | "warleagues/#{ApiFrame::Utils.url_escape( warleague_id)}" }
|
48
|
+
define_endpoint :warleagues, method: :get, endpoint: 'warleagues'
|
49
|
+
|
50
|
+
define_endpoint :location_rankings_clans, method: :get, endpoint: proc { |location_id| "locations/#{ApiFrame::Utils.url_escape(location_id)}/rankings/clans" }
|
51
|
+
define_endpoint :location_rankings_players, method: :get, endpoint: proc { |location_id| "locations/#{ApiFrame::Utils.url_escape(location_id)}/rankings/players" }
|
52
|
+
define_endpoint :location_rankings_playersbuilderbase, method: :get, endpoint: proc { |location_id| "locations/#{ApiFrame::Utils.url_escape(location_id)}/rankings/players-builder-base" }
|
53
|
+
define_endpoint :location_rankings_clansbuilderbase, method: :get, endpoint: proc { |location_id| "locations/#{ApiFrame::Utils.url_escape(location_id)}/rankings/clans-builder-base" }
|
54
|
+
define_endpoint :locations, method: :get, endpoint: 'locations'
|
55
|
+
define_endpoint :location_rankings_capitals, method: :get, endpoint: proc { |location_id| "locations/#{ApiFrame::Utils.url_escape(location_id)}/rankings/capitals" }
|
56
|
+
define_endpoint :location, method: :get, endpoint: proc { |location_id| "locations/#{ApiFrame::Utils.url_escape(location_id)}" }
|
57
|
+
|
58
|
+
define_endpoint :goldpass_seasons_current, method: :get, endpoint: 'goldpass/seasons/current'
|
59
|
+
|
60
|
+
define_endpoint :labels_players, method: :get, endpoint: 'labels/players'
|
61
|
+
define_endpoint :labels_clans, method: :get, endpoint: 'labels/clans'
|
56
62
|
end
|
57
63
|
end
|
@@ -3,6 +3,7 @@ require_relative 'models/paginated_response'
|
|
3
3
|
require_relative 'models/clan'
|
4
4
|
require_relative 'models/player'
|
5
5
|
require_relative 'models/league'
|
6
|
+
require_relative 'models/war'
|
6
7
|
|
7
8
|
module ClashOfClansApi
|
8
9
|
class Client
|
@@ -16,6 +17,26 @@ module ClashOfClansApi
|
|
16
17
|
api.perform_request(:get, 'test').code == '404'
|
17
18
|
end
|
18
19
|
|
20
|
+
def clan_currentwar(clan_tag)
|
21
|
+
Models::War.new(api.clan_currentwar(clan_tag), self)
|
22
|
+
end
|
23
|
+
|
24
|
+
def clan_warlog(clan_tag)
|
25
|
+
Models::PaginatedResponse.new(Models::War, api.clan_warlog(clan_tag), self)
|
26
|
+
end
|
27
|
+
|
28
|
+
def clan(tag)
|
29
|
+
Models::Clan.new(api.clan(tag), self)
|
30
|
+
end
|
31
|
+
|
32
|
+
def clan_members(tag)
|
33
|
+
Models::PaginatedResponse.new(Models::Player, api.clan_members(tag), self)
|
34
|
+
end
|
35
|
+
|
36
|
+
def player(tag)
|
37
|
+
Models::Player.new(api.player(tag), self)
|
38
|
+
end
|
39
|
+
|
19
40
|
def player_verifytoken(player_tag, token)
|
20
41
|
response = api.player_verifytoken(player_tag, token: token)
|
21
42
|
|
@@ -32,28 +53,20 @@ module ClashOfClansApi
|
|
32
53
|
end
|
33
54
|
end
|
34
55
|
|
35
|
-
def
|
36
|
-
Models::
|
37
|
-
end
|
38
|
-
|
39
|
-
def clan_members(tag)
|
40
|
-
Models::PaginatedResponse.new(Models::Player, api.clan_members(tag), self)
|
56
|
+
def capitalleagues
|
57
|
+
Models::PaginatedResponse.new(Models::CapitalLeague, api.capitalleagues, self)
|
41
58
|
end
|
42
59
|
|
43
60
|
def leagues
|
44
61
|
Models::PaginatedResponse.new(Models::League, api.leagues, self)
|
45
62
|
end
|
46
63
|
|
47
|
-
def
|
48
|
-
Models::
|
49
|
-
end
|
50
|
-
|
51
|
-
def player(tag)
|
52
|
-
Models::Player.new(api.player(tag), self)
|
64
|
+
def league_season(league_id=29000022, season_id, limit: 10, before: nil, after: nil) # rubocop:disable Style/OptionalArguments
|
65
|
+
Models::PaginatedResponse.new(Models::Player, api.league_season(league_id, season_id, query: {limit: limit, before: before, after: after}.compact), self)
|
53
66
|
end
|
54
67
|
|
55
|
-
def
|
56
|
-
Models::
|
68
|
+
def league(id)
|
69
|
+
Models::League.new(api.league(id), self)
|
57
70
|
end
|
58
71
|
end
|
59
72
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'invalid_data_error'
|
2
|
+
require 'date'
|
2
3
|
|
3
4
|
module ClashOfClansApi
|
4
5
|
module Models
|
@@ -21,11 +22,13 @@ module ClashOfClansApi
|
|
21
22
|
end
|
22
23
|
|
23
24
|
class << self
|
24
|
-
|
25
|
+
def registered_properties
|
26
|
+
@registered_properties ||= {}
|
27
|
+
end
|
25
28
|
|
26
|
-
def property(
|
27
|
-
define_method(
|
28
|
-
|
29
|
+
def property(method_name, key, type: nil, required: false, default: nil)
|
30
|
+
define_method(method_name) do
|
31
|
+
deduced_type =
|
29
32
|
case type
|
30
33
|
when Symbol
|
31
34
|
send(type)
|
@@ -35,56 +38,59 @@ module ClashOfClansApi
|
|
35
38
|
type
|
36
39
|
end
|
37
40
|
|
38
|
-
if !@hash.key?(key)
|
41
|
+
if !@hash.key?(key)
|
39
42
|
default
|
40
|
-
elsif
|
43
|
+
elsif deduced_type.nil?
|
41
44
|
self[key]
|
42
|
-
elsif property_cached?(
|
43
|
-
property_from_cache(
|
45
|
+
elsif property_cached?(method_name)
|
46
|
+
property_from_cache(method_name)
|
44
47
|
else
|
45
48
|
initializer_proc = proc do |item|
|
46
|
-
if
|
47
|
-
|
49
|
+
if deduced_type.ancestors.include?(ClashOfClansApi::Models::Base)
|
50
|
+
deduced_type.new(item, self.client)
|
51
|
+
elsif deduced_type == DateTime
|
52
|
+
DateTime.parse(item)
|
48
53
|
else
|
49
|
-
|
54
|
+
deduced_type.new(item)
|
50
55
|
end
|
51
56
|
end
|
52
57
|
|
53
|
-
cache_property(
|
58
|
+
cache_property(method_name, self[key].then do |prop|
|
54
59
|
prop.is_a?(Array) ? prop.map(&initializer_proc) : initializer_proc.call(prop)
|
55
60
|
end)
|
56
61
|
end
|
57
62
|
end
|
58
63
|
|
59
|
-
|
60
|
-
|
61
|
-
|
64
|
+
registered_properties[key] = {
|
65
|
+
method_name: method_name,
|
66
|
+
required: required,
|
67
|
+
default: default,
|
68
|
+
type: type,
|
69
|
+
}
|
62
70
|
end
|
63
71
|
end
|
64
72
|
|
65
|
-
def property_cached?(
|
66
|
-
@property_cache && @property_cache.key?(
|
73
|
+
def property_cached?(method_name)
|
74
|
+
@property_cache && @property_cache.key?(method_name)
|
67
75
|
end
|
68
76
|
|
69
|
-
def cache_property(
|
77
|
+
def cache_property(method_name, obj)
|
70
78
|
@property_cache ||= {}
|
71
79
|
|
72
|
-
@property_cache[
|
80
|
+
@property_cache[method_name] = obj
|
73
81
|
end
|
74
82
|
|
75
|
-
def property_from_cache(
|
76
|
-
@property_cache[
|
83
|
+
def property_from_cache(method_name)
|
84
|
+
@property_cache[method_name]
|
77
85
|
end
|
78
86
|
|
79
87
|
def validate!
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
raise InvalidDataError, "The following keys are required, but missing from the model data: #{missing.map(&:inspect).join(', ')}"
|
87
|
-
end
|
88
|
+
missing = self.class.registered_properties.reject do |field_name, properties|
|
89
|
+
!properties[:required] || @hash.key?(field_name)
|
90
|
+
end
|
91
|
+
|
92
|
+
if missing.any?
|
93
|
+
raise InvalidDataError, "The following keys are required, but missing from the model data: #{missing.keys.map(&:inspect).join(', ')}"
|
88
94
|
end
|
89
95
|
end
|
90
96
|
end
|
@@ -1,32 +1,42 @@
|
|
1
1
|
require_relative 'base'
|
2
|
+
require_relative 'capital_league'
|
3
|
+
require_relative 'chat_language'
|
4
|
+
require_relative 'clan_capital'
|
5
|
+
require_relative 'clan_location'
|
2
6
|
require_relative 'icon_set'
|
3
7
|
require_relative 'label'
|
8
|
+
require_relative 'war_league'
|
4
9
|
|
5
10
|
module ClashOfClansApi
|
6
11
|
module Models
|
7
12
|
class Clan < Base
|
8
|
-
property :tag,
|
9
|
-
property :name,
|
10
|
-
property :
|
11
|
-
property :
|
12
|
-
property :
|
13
|
-
property :
|
14
|
-
property :
|
15
|
-
property :
|
16
|
-
property :
|
17
|
-
property :
|
18
|
-
property :
|
19
|
-
property :
|
20
|
-
property :
|
21
|
-
property :
|
22
|
-
property :
|
23
|
-
property :
|
24
|
-
property :
|
25
|
-
property :
|
26
|
-
property :
|
27
|
-
property :
|
28
|
-
property :
|
29
|
-
property :
|
13
|
+
property :tag, 'tag', required: true
|
14
|
+
property :name, 'name', required: true
|
15
|
+
property :type, 'type'
|
16
|
+
property :description, 'description'
|
17
|
+
property :location, 'location', type: ClanLocation
|
18
|
+
property :family_friendly?, 'isFamilyFriendly'
|
19
|
+
property :badge_urls, 'badgeUrls', type: IconSet
|
20
|
+
property :clan_level, 'clanLevel'
|
21
|
+
property :clan_points, 'clanPoints'
|
22
|
+
property :clan_builder_base_points, 'clanBuilderBasePoints'
|
23
|
+
property :clan_capital_points, 'clanCapitalPoints'
|
24
|
+
property :capital_league, 'capitalLeague', type: CapitalLeague
|
25
|
+
property :required_trophies, 'requiredTrophies'
|
26
|
+
property :war_frequency, 'warFrequency'
|
27
|
+
property :war_win_streak, 'warWinStreak'
|
28
|
+
property :war_wins, 'warWins'
|
29
|
+
property :war_ties, 'warTies'
|
30
|
+
property :war_losses, 'warLosses'
|
31
|
+
property :war_log_public?, 'isWarLogPublic'
|
32
|
+
property :war_league, 'warLeague', type: WarLeague
|
33
|
+
property :members, 'members'
|
34
|
+
property :member_list, 'memberList', type: 'ClashOfClansApi::Models::Player'
|
35
|
+
property :labels, 'labels', type: Label
|
36
|
+
property :required_builder_base_trophies, 'requiredBuilderBaseTrophies'
|
37
|
+
property :required_townhall_level, 'requiredTownhallLevel'
|
38
|
+
property :clan_capital, 'clanCapital', type: ClanCapital
|
39
|
+
property :chat_language, 'chatLanguage', type: ChatLanguage
|
30
40
|
end
|
31
41
|
end
|
32
42
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
require_relative 'clan_capital_district'
|
3
|
+
|
4
|
+
module ClashOfClansApi
|
5
|
+
module Models
|
6
|
+
class ClanCapital < Base
|
7
|
+
property :capital_hall_level, 'capitalHallLevel', required: true
|
8
|
+
property :districts, 'districts', required: true, type: ClanCapitalDistrict
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
module ClashOfClansApi
|
4
|
+
module Models
|
5
|
+
class ClanCapitalDistrict < Base
|
6
|
+
property :id, 'id', required: true
|
7
|
+
property :name, 'name', required: true
|
8
|
+
property :district_hall_level, 'districtHallLevel', required: true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'base'
|
2
|
+
require_relative 'hero_equipment'
|
2
3
|
|
3
4
|
module ClashOfClansApi
|
4
5
|
module Models
|
@@ -7,6 +8,7 @@ module ClashOfClansApi
|
|
7
8
|
property :level, 'level', required: true
|
8
9
|
property :max_level, 'maxLevel', required: true
|
9
10
|
property :village, 'village', required: true
|
11
|
+
property :equipment, 'equipment', type: HeroEquipment
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
module ClashOfClansApi
|
4
|
+
module Models
|
5
|
+
class HeroEquipment < Base
|
6
|
+
property :name, 'name', required: true
|
7
|
+
property :level, 'level', required: true
|
8
|
+
property :max_level, 'maxLevel', required: true
|
9
|
+
property :village, 'village', required: true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
require_relative 'base'
|
2
|
+
require_relative 'pagination_paging'
|
2
3
|
|
3
4
|
module ClashOfClansApi
|
4
5
|
module Models
|
5
6
|
class PaginatedResponse < Base
|
6
7
|
attr_accessor :item_type
|
7
8
|
|
8
|
-
property :items, 'items',
|
9
|
-
property :paging, 'paging'
|
9
|
+
property :items, 'items', required: true, type: :item_type
|
10
|
+
property :paging, 'paging', required: true, type: PaginationPaging
|
10
11
|
|
11
12
|
def initialize(item_type, hash, client)
|
12
13
|
self.item_type = item_type
|
@@ -1,43 +1,50 @@
|
|
1
1
|
require_relative 'base'
|
2
2
|
require_relative 'achievement'
|
3
|
+
require_relative 'builder_base_league'
|
3
4
|
require_relative 'hero'
|
5
|
+
require_relative 'hero_equipment'
|
4
6
|
require_relative 'label'
|
5
7
|
require_relative 'league'
|
6
8
|
require_relative 'legend_statistics'
|
9
|
+
require_relative 'player_house'
|
7
10
|
require_relative 'spell'
|
8
11
|
require_relative 'troop'
|
9
12
|
|
10
13
|
module ClashOfClansApi
|
11
14
|
module Models
|
12
15
|
class Player < Base
|
13
|
-
property :tag,
|
14
|
-
property :name,
|
15
|
-
property :town_hall_level,
|
16
|
-
property :town_hall_weapon_level,
|
17
|
-
property :exp_level,
|
18
|
-
property :trophies,
|
19
|
-
property :best_trophies,
|
20
|
-
property :war_stars,
|
21
|
-
property :attack_wins,
|
22
|
-
property :defense_wins,
|
23
|
-
property :builder_hall_level,
|
24
|
-
property :
|
25
|
-
property :
|
26
|
-
property :
|
27
|
-
property :
|
28
|
-
property :
|
29
|
-
property :
|
30
|
-
property :
|
31
|
-
property :
|
32
|
-
property :
|
33
|
-
property :
|
34
|
-
property :
|
35
|
-
property :
|
36
|
-
property :
|
37
|
-
property :
|
38
|
-
property :
|
39
|
-
property :
|
40
|
-
property :
|
16
|
+
property :tag, 'tag', required: true
|
17
|
+
property :name, 'name', required: true
|
18
|
+
property :town_hall_level, 'townHallLevel'
|
19
|
+
property :town_hall_weapon_level, 'townHallWeaponLevel'
|
20
|
+
property :exp_level, 'expLevel'
|
21
|
+
property :trophies, 'trophies'
|
22
|
+
property :best_trophies, 'bestTrophies'
|
23
|
+
property :war_stars, 'warStars'
|
24
|
+
property :attack_wins, 'attackWins'
|
25
|
+
property :defense_wins, 'defenseWins'
|
26
|
+
property :builder_hall_level, 'builderHallLevel'
|
27
|
+
property :builder_base_trophies, 'builderBaseTrophies'
|
28
|
+
property :best_builder_base_trophies, 'bestBuilderBaseTrophies'
|
29
|
+
property :role, 'role'
|
30
|
+
property :war_preference, 'warPreference'
|
31
|
+
property :clan_rank, 'clanRank'
|
32
|
+
property :previous_clan_rank, 'previousClanRank'
|
33
|
+
property :donations, 'donations'
|
34
|
+
property :donations_received, 'donationsReceived'
|
35
|
+
property :rank, 'rank'
|
36
|
+
property :clan_capital_contributions, 'clanCapitalContributions'
|
37
|
+
property :clan, 'clan', type: 'ClashOfClansApi::Models::Clan'
|
38
|
+
property :league, 'league', type: League
|
39
|
+
property :builder_base_league, 'builderBaseLeague', type: BuilderBaseLeague
|
40
|
+
property :legend_statistics, 'legendStatistics', type: LegendStatistics
|
41
|
+
property :achievements, 'achievements', type: Achievement
|
42
|
+
property :player_house, 'playerHouse', type: PlayerHouse
|
43
|
+
property :labels, 'labels', type: Label
|
44
|
+
property :troops, 'troops', type: Troop
|
45
|
+
property :heroes, 'heroes', type: Hero
|
46
|
+
property :spells, 'spells', type: Spell
|
47
|
+
property :hero_equipment, 'heroEquipment', type: HeroEquipment
|
41
48
|
end
|
42
49
|
end
|
43
50
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
require_relative 'war_clan'
|
3
|
+
|
4
|
+
module ClashOfClansApi
|
5
|
+
module Models
|
6
|
+
class War < Base
|
7
|
+
property :state, 'state'
|
8
|
+
property :result, 'result'
|
9
|
+
property :start_time, 'startTime', type: DateTime
|
10
|
+
property :end_time, 'endTime', type: DateTime
|
11
|
+
property :preparation_start_time, 'preparationStartTime', type: DateTime
|
12
|
+
property :team_size, 'teamSize'
|
13
|
+
property :attacks_per_member, 'attacksPerMember'
|
14
|
+
property :clan, 'clan', required: true, type: WarClan
|
15
|
+
property :opponent, 'opponent', required: true, type: WarClan
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
module ClashOfClansApi
|
4
|
+
module Models
|
5
|
+
class WarAttack < Base
|
6
|
+
property :attacker_tag, 'attackerTag', required: true
|
7
|
+
property :defender_tag, 'defenderTag', required: true
|
8
|
+
property :stars, 'stars', required: true
|
9
|
+
property :destruction_percentage, 'destructionPercentage', required: true
|
10
|
+
property :order, 'order', required: true
|
11
|
+
property :duration, 'duration', required: true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
require_relative 'icon_set'
|
3
|
+
require_relative 'war_clan_member'
|
4
|
+
|
5
|
+
module ClashOfClansApi
|
6
|
+
module Models
|
7
|
+
class WarClan < Base
|
8
|
+
property :tag, 'tag'
|
9
|
+
property :name, 'name'
|
10
|
+
property :badge_urls, 'badgeUrls', type: IconSet
|
11
|
+
property :clan_level, 'clanLevel'
|
12
|
+
property :attacks, 'attacks'
|
13
|
+
property :stars, 'stars'
|
14
|
+
property :destruction_percentage, 'destructionPercentage'
|
15
|
+
property :exp_earned, 'expEarned'
|
16
|
+
property :members, 'members', type: WarClanMember
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
require_relative 'war_attack'
|
3
|
+
|
4
|
+
module ClashOfClansApi
|
5
|
+
module Models
|
6
|
+
class WarClanMember < Base
|
7
|
+
property :tag, 'tag', required: true
|
8
|
+
property :name, 'name', required: true
|
9
|
+
property :townhall_level, 'townhallLevel'
|
10
|
+
property :map_position, 'mapPosition'
|
11
|
+
property :attacks, 'attacks', type: WarAttack
|
12
|
+
property :opponent_attacks, 'opponentAttacks'
|
13
|
+
property :best_opponent_attack, 'bestOpponentAttack', type: WarAttack
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
|
-
|
1
|
+
require 'api_frame'
|
2
2
|
|
3
3
|
module ClashOfClansApi
|
4
4
|
module TokenApi
|
5
5
|
BASE_URI = URI('https://developer.clashofclans.com/api/')
|
6
6
|
|
7
7
|
class << self
|
8
|
-
include EndpointMethods
|
8
|
+
include ApiFrame::EndpointMethods
|
9
9
|
|
10
10
|
def base_uri
|
11
11
|
BASE_URI
|
@@ -21,7 +21,7 @@ module ClashOfClansApi
|
|
21
21
|
'Cookie' => "session=#{cookies['session'][0]}",
|
22
22
|
}
|
23
23
|
else
|
24
|
-
raise NoSuccessError, response
|
24
|
+
raise ApiFrame::NoSuccessError, response
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -52,6 +52,20 @@ module ClashOfClansApi
|
|
52
52
|
true
|
53
53
|
end
|
54
54
|
|
55
|
+
def create_or_get_api_key_for_current_ipv4_address(name, description=name, overwrite: false)
|
56
|
+
current_ipv4 = ClashOfClansApi::Utils.current_ipv4_address
|
57
|
+
token = list_api_keys.select{ |i| i.name == name }.first
|
58
|
+
|
59
|
+
if token && token.cidr_ranges.include?(current_ipv4)
|
60
|
+
token
|
61
|
+
elsif (token && overwrite) || !token
|
62
|
+
token&.revoke
|
63
|
+
create_api_key(name, description, current_ipv4)
|
64
|
+
else
|
65
|
+
false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
55
69
|
class << self
|
56
70
|
def create!(email, password)
|
57
71
|
new(email, password).login!
|
@@ -2,31 +2,6 @@ require 'open-uri'
|
|
2
2
|
|
3
3
|
module ClashOfClansApi
|
4
4
|
module Utils
|
5
|
-
def self.url_escape(string)
|
6
|
-
if !string.nil?
|
7
|
-
CGI.escape(string.to_s)
|
8
|
-
else
|
9
|
-
raise TypeError, 'cannot escape nil'
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.call_proc_without_unknown_keywords(proc, *args, **kwargs, &block)
|
14
|
-
params = proc.parameters.group_by(&:first).transform_values! do |m|
|
15
|
-
m.map do |s|
|
16
|
-
s[1]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
proc_keys =
|
21
|
-
if params.key?(:keyrest)
|
22
|
-
kwargs
|
23
|
-
else
|
24
|
-
kwargs.slice(*params.values_at(:key, :keyreq).compact.flatten)
|
25
|
-
end
|
26
|
-
|
27
|
-
proc.call(*args, **proc_keys, &block)
|
28
|
-
end
|
29
|
-
|
30
5
|
def self.current_ipv4_address
|
31
6
|
IPAddr.new(URI('https://ipv4.icanhazip.com').open.read.strip).to_s
|
32
7
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clash_of_clans_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- expeehaa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2023-12-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: api_frame
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
description:
|
14
28
|
email:
|
15
29
|
- expeehaa@outlook.com
|
@@ -21,11 +35,17 @@ files:
|
|
21
35
|
- lib/clash_of_clans_api.rb
|
22
36
|
- lib/clash_of_clans_api/api.rb
|
23
37
|
- lib/clash_of_clans_api/client.rb
|
24
|
-
- lib/clash_of_clans_api/endpoint_methods.rb
|
25
38
|
- lib/clash_of_clans_api/models/achievement.rb
|
26
39
|
- lib/clash_of_clans_api/models/base.rb
|
40
|
+
- lib/clash_of_clans_api/models/builder_base_league.rb
|
41
|
+
- lib/clash_of_clans_api/models/capital_league.rb
|
42
|
+
- lib/clash_of_clans_api/models/chat_language.rb
|
27
43
|
- lib/clash_of_clans_api/models/clan.rb
|
44
|
+
- lib/clash_of_clans_api/models/clan_capital.rb
|
45
|
+
- lib/clash_of_clans_api/models/clan_capital_district.rb
|
46
|
+
- lib/clash_of_clans_api/models/clan_location.rb
|
28
47
|
- lib/clash_of_clans_api/models/hero.rb
|
48
|
+
- lib/clash_of_clans_api/models/hero_equipment.rb
|
29
49
|
- lib/clash_of_clans_api/models/icon_set.rb
|
30
50
|
- lib/clash_of_clans_api/models/invalid_data_error.rb
|
31
51
|
- lib/clash_of_clans_api/models/label.rb
|
@@ -33,11 +53,19 @@ files:
|
|
33
53
|
- lib/clash_of_clans_api/models/legend_season.rb
|
34
54
|
- lib/clash_of_clans_api/models/legend_statistics.rb
|
35
55
|
- lib/clash_of_clans_api/models/paginated_response.rb
|
56
|
+
- lib/clash_of_clans_api/models/pagination_cursors.rb
|
57
|
+
- lib/clash_of_clans_api/models/pagination_paging.rb
|
36
58
|
- lib/clash_of_clans_api/models/player.rb
|
59
|
+
- lib/clash_of_clans_api/models/player_house.rb
|
60
|
+
- lib/clash_of_clans_api/models/player_house_element.rb
|
37
61
|
- lib/clash_of_clans_api/models/spell.rb
|
38
62
|
- lib/clash_of_clans_api/models/token.rb
|
39
63
|
- lib/clash_of_clans_api/models/troop.rb
|
40
|
-
- lib/clash_of_clans_api/
|
64
|
+
- lib/clash_of_clans_api/models/war.rb
|
65
|
+
- lib/clash_of_clans_api/models/war_attack.rb
|
66
|
+
- lib/clash_of_clans_api/models/war_clan.rb
|
67
|
+
- lib/clash_of_clans_api/models/war_clan_member.rb
|
68
|
+
- lib/clash_of_clans_api/models/war_league.rb
|
41
69
|
- lib/clash_of_clans_api/tags.rb
|
42
70
|
- lib/clash_of_clans_api/token_api.rb
|
43
71
|
- lib/clash_of_clans_api/token_client.rb
|
@@ -56,14 +84,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
56
84
|
requirements:
|
57
85
|
- - ">="
|
58
86
|
- !ruby/object:Gem::Version
|
59
|
-
version:
|
87
|
+
version: 3.0.0
|
60
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
89
|
requirements:
|
62
90
|
- - ">="
|
63
91
|
- !ruby/object:Gem::Version
|
64
92
|
version: '0'
|
65
93
|
requirements: []
|
66
|
-
rubygems_version: 3.
|
94
|
+
rubygems_version: 3.4.10
|
67
95
|
signing_key:
|
68
96
|
specification_version: 4
|
69
97
|
summary: Client library for interacting with the ClashOfClans API.
|
@@ -1,67 +0,0 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
require 'json'
|
3
|
-
require 'net/https'
|
4
|
-
|
5
|
-
module ClashOfClansApi
|
6
|
-
module EndpointMethods
|
7
|
-
def endpoint_headers
|
8
|
-
{}
|
9
|
-
end
|
10
|
-
|
11
|
-
def perform_request(method, api_path, query: nil, body: nil, headers: nil)
|
12
|
-
uri = self.base_uri + api_path
|
13
|
-
uri.query = URI.encode_www_form(query) if query
|
14
|
-
|
15
|
-
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
16
|
-
case method
|
17
|
-
when :get
|
18
|
-
Net::HTTP::Get
|
19
|
-
when :post
|
20
|
-
Net::HTTP::Post
|
21
|
-
else
|
22
|
-
raise ArgumentError, "Invalid method #{method.inspect}."
|
23
|
-
end.new(uri).tap do |request|
|
24
|
-
endpoint_headers.merge(headers || {}).each do |name, value|
|
25
|
-
request[name] = value
|
26
|
-
end
|
27
|
-
|
28
|
-
if body
|
29
|
-
request['Content-Type'] = 'application/json'
|
30
|
-
request.body = body
|
31
|
-
end
|
32
|
-
end.then do |request|
|
33
|
-
http.request(request)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def transform_response(response)
|
39
|
-
if response.is_a?(Net::HTTPSuccess)
|
40
|
-
JSON.parse(response.body)
|
41
|
-
else
|
42
|
-
raise NoSuccessError, response
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.included(klass)
|
47
|
-
klass.extend(ClassMethods)
|
48
|
-
end
|
49
|
-
|
50
|
-
module ClassMethods
|
51
|
-
def define_endpoint(name, method:, endpoint:, body: nil)
|
52
|
-
define_method(name) do |*args, **kwargs|
|
53
|
-
uri = endpoint.respond_to?(:call) ? ClashOfClansApi::Utils.call_proc_without_unknown_keywords(endpoint, *args, **kwargs) : endpoint
|
54
|
-
request_body = body .respond_to?(:call) ? ClashOfClansApi::Utils.call_proc_without_unknown_keywords(body, *args, **kwargs) : body
|
55
|
-
|
56
|
-
perform_request(method, uri, body: request_body, query: kwargs.key?(:query) ? kwargs.fetch(:query) : nil, headers: kwargs.key?(:headers) ? kwargs.fetch(:headers) : nil).then do |response|
|
57
|
-
if !kwargs.key?(:plain_response) || !kwargs.fetch(:plain_response)
|
58
|
-
transform_response(response)
|
59
|
-
else
|
60
|
-
response
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|