shikimori-api 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +20 -0
  3. data/lib/shikimori/api/client.rb +34 -0
  4. data/lib/shikimori/api/errors.rb +21 -0
  5. data/lib/shikimori/api/rest.rb +115 -0
  6. data/lib/shikimori/api/uri.rb +18 -0
  7. data/lib/shikimori/api/v1/achievements.rb +32 -0
  8. data/lib/shikimori/api/v1/animes.rb +252 -0
  9. data/lib/shikimori/api/v1/appear.rb +40 -0
  10. data/lib/shikimori/api/v1/bans.rb +31 -0
  11. data/lib/shikimori/api/v1/calendars.rb +32 -0
  12. data/lib/shikimori/api/v1/characters.rb +52 -0
  13. data/lib/shikimori/api/v1/clubs.rb +329 -0
  14. data/lib/shikimori/api/v1/comments.rb +161 -0
  15. data/lib/shikimori/api/v1/constants.rb +107 -0
  16. data/lib/shikimori/api/v1/dialogs.rb +78 -0
  17. data/lib/shikimori/api/v1/favorites.rb +148 -0
  18. data/lib/shikimori/api/v1/forums.rb +31 -0
  19. data/lib/shikimori/api/v1/friends.rb +57 -0
  20. data/lib/shikimori/api/v1/genres.rb +31 -0
  21. data/lib/shikimori/api/v1/ignores.rb +62 -0
  22. data/lib/shikimori/api/v1/mangas.rb +211 -0
  23. data/lib/shikimori/api/v1/messages.rb +168 -0
  24. data/lib/shikimori/api/v1/people.rb +53 -0
  25. data/lib/shikimori/api/v1/publishers.rb +31 -0
  26. data/lib/shikimori/api/v1/ranobe.rb +206 -0
  27. data/lib/shikimori/api/v1/reviews.rb +89 -0
  28. data/lib/shikimori/api/v1/stats.rb +31 -0
  29. data/lib/shikimori/api/v1/studios.rb +31 -0
  30. data/lib/shikimori/api/v1/styles.rb +112 -0
  31. data/lib/shikimori/api/v1/topic_ignores.rb +63 -0
  32. data/lib/shikimori/api/v1/topics.rb +237 -0
  33. data/lib/shikimori/api/v1/user_images.rb +36 -0
  34. data/lib/shikimori/api/v1/user_rates.rb +194 -0
  35. data/lib/shikimori/api/v1/users.rb +310 -0
  36. data/lib/shikimori/api/v1/videos.rb +85 -0
  37. data/lib/shikimori/api/v1.rb +77 -0
  38. data/lib/shikimori/api/v2/abuse_requests.rb +103 -0
  39. data/lib/shikimori/api/v2/episode_notifications.rb +54 -0
  40. data/lib/shikimori/api/v2/topic_ignore.rb +54 -0
  41. data/lib/shikimori/api/v2/user_ignore.rb +54 -0
  42. data/lib/shikimori/api/v2/user_rates.rb +171 -0
  43. data/lib/shikimori/api/v2.rb +27 -0
  44. data/lib/shikimori/api/version.rb +8 -0
  45. data/lib/shikimori/api.rb +14 -0
  46. data/lib/shikimori-api.rb +3 -0
  47. data/shikimori-api.gemspec +40 -0
  48. data/sig/shikimori/api/client.rbs +12 -0
  49. data/sig/shikimori/api/rest.rbs +30 -0
  50. data/sig/shikimori/api/uri.rbs +10 -0
  51. data/sig/shikimori/api/v1/achievements.rbs +15 -0
  52. data/sig/shikimori/api/v1/animes.rbs +23 -0
  53. data/sig/shikimori/api/v1/appear.rbs +15 -0
  54. data/sig/shikimori/api/v1/bans.rbs +15 -0
  55. data/sig/shikimori/api/v1/calendars.rbs +15 -0
  56. data/sig/shikimori/api/v1/characters.rbs +16 -0
  57. data/sig/shikimori/api/v1/clubs.rbs +29 -0
  58. data/sig/shikimori/api/v1/comments.rbs +19 -0
  59. data/sig/shikimori/api/v1/constants.rbs +19 -0
  60. data/sig/shikimori/api/v1/dialogs.rbs +17 -0
  61. data/sig/shikimori/api/v1/favorites.rbs +23 -0
  62. data/sig/shikimori/api/v1/forums.rbs +15 -0
  63. data/sig/shikimori/api/v1/friends.rbs +16 -0
  64. data/sig/shikimori/api/v1/genres.rbs +15 -0
  65. data/sig/shikimori/api/v1/ignores.rbs +16 -0
  66. data/sig/shikimori/api/v1/mangas.rbs +23 -0
  67. data/sig/shikimori/api/v1/messages.rbs +20 -0
  68. data/sig/shikimori/api/v1/people.rbs +16 -0
  69. data/sig/shikimori/api/v1/publishers.rbs +15 -0
  70. data/sig/shikimori/api/v1/ranobe.rbs +23 -0
  71. data/sig/shikimori/api/v1/reviews.rbs +19 -0
  72. data/sig/shikimori/api/v1/stats.rbs +15 -0
  73. data/sig/shikimori/api/v1/studios.rbs +15 -0
  74. data/sig/shikimori/api/v1/styles.rbs +18 -0
  75. data/sig/shikimori/api/v1/topic_ignores.rbs +16 -0
  76. data/sig/shikimori/api/v1/topics.rbs +40 -0
  77. data/sig/shikimori/api/v1/user_images.rbs +15 -0
  78. data/sig/shikimori/api/v1/user_rates.rbs +44 -0
  79. data/sig/shikimori/api/v1/users.rbs +28 -0
  80. data/sig/shikimori/api/v1/videos.rbs +23 -0
  81. data/sig/shikimori/api/v1.rbs +41 -0
  82. data/sig/shikimori/api/v2/abuse_requests.rbs +18 -0
  83. data/sig/shikimori/api/v2/episode_notifications.rbs +25 -0
  84. data/sig/shikimori/api/v2/topic_ignore.rbs +16 -0
  85. data/sig/shikimori/api/v2/user_ignore.rbs +16 -0
  86. data/sig/shikimori/api/v2/user_rates.rbs +43 -0
  87. data/sig/shikimori/api/v2.rbs +16 -0
  88. data/sig/shikimori/api/version.rbs +5 -0
  89. data/sig/shikimori/api.rbs +18 -0
  90. metadata +137 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 47e86dd12c49f262d518820a7c3572c8de8a73a2d7047891819a2c6be46daf83
4
+ data.tar.gz: 1b2872e10096765da94493d387061870757a041405fbd54a4baf76e5da19c04b
5
+ SHA512:
6
+ metadata.gz: acfec6a1d8fdf30813debd7fe2dbf423f4c531a48e2c57c8ee43b7b243e69824de8c7a30aa40e1ec64bb48d94497725077ac84811a27f3f1d6f28cad4b589cc3
7
+ data.tar.gz: d253b3dc0191aec63c8aaca69ea258c9f63cdaf5d2cc31f140d628acfbec18abf1bf65dcfb5bccccd2025373fe8f867a8723b05ee4399d0a02353fd1611b34a6
data/README.md ADDED
@@ -0,0 +1,20 @@
1
+ [![CI](https://github.com/iwdt/shikikit/actions/workflows/main.yml/badge.svg)](https://github.com/iwdt/shikikit/actions/workflows/main.yml) [![codecov](https://codecov.io/gh/iwdt/shikikit/graph/badge.svg)](https://codecov.io/gh/iwdt/shikikit)
2
+
3
+ # Shikikit
4
+ Ruby toolkit for the [Shikimori API](https://shikimori.one)
5
+
6
+ ## TODO:
7
+ - logger
8
+ - #as_app
9
+ - proxy config
10
+ - oauth methods on API
11
+ - optional auto refresh token
12
+ - more information at errors
13
+ - more tests
14
+ - entities for responses
15
+ - contracts for requests (client-side validations)
16
+ - better documentation
17
+ - mutator
18
+ - CI/CD
19
+ - auto version increment on main branch pushing
20
+ - deploy to rubygems
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'rest'
4
+ require_relative 'uri'
5
+ require_relative 'v1'
6
+ require_relative 'v2'
7
+
8
+ module Shikimori
9
+ module API
10
+ # Client to call shikimoris API
11
+ class Client
12
+ # @return [String] Default site url
13
+ DEFAULT_SITE_URL = 'https://shikimori.one/'
14
+
15
+ attr_reader :v1, :v2
16
+
17
+ def initialize(site = DEFAULT_SITE_URL, app_name:, access_token:, refresh_token:)
18
+ rest = REST.new(
19
+ access_token: access_token,
20
+ refresh_token: refresh_token,
21
+ app_name: app_name
22
+ )
23
+ @v1 = V1.new(
24
+ base_url: URI.new(site).join('api/'),
25
+ rest: rest
26
+ )
27
+ @v2 = V2.new(
28
+ base_url: URI.new(site).join('api/v2/'),
29
+ rest: rest
30
+ )
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shikimori
4
+ module API
5
+ class RequestError < StandardError; end
6
+
7
+ class NotFoundError < RequestError; end
8
+ class ForbiddenError < RequestError; end
9
+
10
+ # Error, when request is bad
11
+ class BadRequestError < RequestError
12
+ attr_reader :errors
13
+
14
+ def initialize(errors)
15
+ @errors = errors.is_a?(Hash) ? errors['errors'] : errors
16
+
17
+ super("Bad request. Errors:\n\t#{@errors.join("\n\t")}")
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shikimori
4
+ module API
5
+ # Helpers to make requests
6
+ class REST
7
+ def initialize(app_name:, access_token:, refresh_token:)
8
+ @app_name = app_name
9
+ @access_token = access_token
10
+ @refresh_token = refresh_token
11
+ end
12
+
13
+ def get(uri, **options)
14
+ _response, json = request(:get, uri, **options)
15
+ json
16
+ end
17
+
18
+ def post(uri, data, **options)
19
+ _response, json = request(:post, uri, data, **options)
20
+ json
21
+ end
22
+
23
+ def put(uri, data, **options)
24
+ _response, json = request(:put, uri, data, **options)
25
+ json
26
+ end
27
+
28
+ def delete(uri, **options)
29
+ response, _json = request(:delete, uri, **options)
30
+ [Net::HTTPNoContent, Net::HTTPSuccess].any? { response.is_a?(_1) }
31
+ end
32
+
33
+ private
34
+
35
+ def request(method, uri, body = nil, **options)
36
+ request = build_request(method, uri, **options)
37
+ response = start_request(uri, request, body, **options)
38
+
39
+ [response, parse_response(response)]
40
+ end
41
+
42
+ def build_request(method, uri, **options)
43
+ headers = headers_from(options)
44
+ query = query_params_from(uri, options)
45
+ uri.query = query if !query.nil? && !query.empty?
46
+
47
+ case method
48
+ when :get
49
+ Net::HTTP::Get.new(uri, headers)
50
+ when :post
51
+ Net::HTTP::Post.new(uri, headers)
52
+ when :put
53
+ Net::HTTP::Put.new(uri, headers)
54
+ when :delete
55
+ Net::HTTP::Delete.new(uri, headers)
56
+ end
57
+ end
58
+
59
+ def start_request(uri, request, body = nil, **options)
60
+ unless body.nil?
61
+ if options.fetch(:as_form, false)
62
+ request.set_form(body, 'multipart/form-data')
63
+ else
64
+ request.body = body.to_json
65
+ end
66
+ end
67
+
68
+ Net::HTTP.start(
69
+ uri.hostname.to_s, uri.port,
70
+ :ENV, nil, nil, nil,
71
+ use_ssl: uri.scheme == 'https'
72
+ ) do |http|
73
+ http.request(request)
74
+ end
75
+ end
76
+
77
+ def parse_response(response)
78
+ case response
79
+ when Net::HTTPNoContent
80
+ {}
81
+ when Net::HTTPSuccess, Net::HTTPCreated
82
+ json_parse_response_body(response.body)
83
+ when Net::HTTPForbidden
84
+ raise ForbiddenError
85
+ when Net::HTTPNotFound
86
+ raise NotFoundError
87
+ when Net::HTTPUnprocessableEntity, Net::HTTPBadRequest
88
+ raise BadRequestError, json_parse_response_body(response.body)
89
+ end
90
+ end
91
+
92
+ def json_parse_response_body(body)
93
+ JSON.parse(body&.empty? ? '{}' : body)
94
+ rescue JSON::ParserError
95
+ {}
96
+ end
97
+
98
+ def headers_from(options)
99
+ (options[:headers] || {}).merge(
100
+ 'Content-Type' => 'application/json',
101
+ 'Authorization' => "Bearer #{@access_token}",
102
+ 'User-Agent' => @app_name
103
+ )
104
+ end
105
+
106
+ def query_params_from(uri, options)
107
+ queries = ::URI.decode_www_form uri.query || ''
108
+ (options[:query] || {}).each do |key, value|
109
+ queries << [key, value]
110
+ end
111
+ ::URI.encode_www_form(queries)
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shikimori
4
+ module API
5
+ # Helper to working with URI object
6
+ class URI
7
+ attr_reader :url
8
+
9
+ def initialize(uri)
10
+ @url = URI(uri.to_s)
11
+ end
12
+
13
+ def join(*path)
14
+ self.class.new ::URI.join(@url, path.join('/'))
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shikimori
4
+ module API
5
+ class V1
6
+ # Methods for the Achievements API
7
+ #
8
+ # @see https://shikimori.one/api/doc/1.0/achievements Shikimori's API documentation
9
+ module Achievements
10
+ # Get list of Achievements
11
+ #
12
+ # @param user_id [Integer] User's ID
13
+ # @param headers [Hash] Request headers
14
+ # @param query [Hash] Query string parameters for request
15
+ #
16
+ # @return [Array<Hash>] Array of hashes representing user's achievements
17
+ #
18
+ # @see https://shikimori.one/api/doc/1.0/achievements/index Shikimori's API documentation
19
+ # @example Get a achievements for user with id equal to 1
20
+ # client = Shikimori::API::Client.new(
21
+ # app_name: 'Api Test',
22
+ # aceess_token: '****',
23
+ # refresh_token: '****'
24
+ # )
25
+ # client.v1.achievements(user_id: 1) #=> [{ id: 1, ... }]
26
+ def achievements(user_id:, headers: nil, **query)
27
+ rest.get base_url.join('achievements').url, headers: headers, query: { user_id: user_id }.merge(query)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,252 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shikimori
4
+ module API
5
+ class V1
6
+ # Methods for the Animes API
7
+ #
8
+ # @see https://shikimori.one/api/doc/1.0/animes Shikimori's API documentation
9
+ module Animes
10
+ # Get list of anime titles
11
+ #
12
+ # @param headers [Hash] Request headers
13
+ # @param query [Hash] Filters and pagination for animes
14
+ # @option query [Integer] :page Number of page. Must be between 1 and 100000
15
+ # @option query [Integer] :limit Number of titles per page. Must be a lower or equal that 50
16
+ # @option query ["id", "id_desc", "ranked",
17
+ # "kind", "popularity", "name",
18
+ # "aired_on", "episodes", "status",
19
+ # "random", "ranked_random",
20
+ # "ranked_shiki", "created_at", "created_at_desc"] :order Sorting type.
21
+ # @option query [String, Symbol] :type Type of title. Deprecated! use :kind instead
22
+ # @option query ["tv", "movie", "ova",
23
+ # "ona", "special", "tv_special",
24
+ # "music", "pv", "cm", "tv_13",
25
+ # "tv_24", "tv_48"] :kind Type of anime title
26
+ # @option query ["anons", "ongoing", "released"] :status Anime title status
27
+ # @option query [String] :season Anime season. Examples: "summer_2017", "2016", "2014_2016", "199x"
28
+ # @option query [Integer] :score Minimal anime score
29
+ # @option query ["S", "D", "F"] :duration Duration of anime title episode,
30
+ # where S – less than 10 minutes, D – less than 30 minutes and F – more than 30 minutes
31
+ # @option query ["none", "g", "pg", "pg_13", "r", "r_plus", "rx"] :rating Age limit level of anime title
32
+ # @option query [String] :genre List of genre ids separated by comma
33
+ # @option query [String] :genre_v2 List of genre v2 ids separated by comma
34
+ # @option query [String] :studio List of studio ids separated by comma
35
+ # @option query [String] :franchise List of franchises separated by comma
36
+ # @option query [TrueClass, FalseClass] :censored Set to false to allow hentai, yaoi and yuri
37
+ # @option query ["planned", "watching", "rewatching",
38
+ # "completed", "on_hold", "dropped"] :mylist Status of anime in current user list
39
+ # @option query [String] :ids List of anime ids separated by comma
40
+ # @option query [String] :exclude_ids List of anime ids separated by comma
41
+ # @option query [String] :search Search phrase to filter animes by name
42
+ #
43
+ # @return [Array<Hash>] Array of hashes representing animes
44
+ #
45
+ # @see https://shikimori.one/api/doc/1.0/animes/index Shikimori's API documentation
46
+ # @example Get 20 anime titles on second page
47
+ # client = Shikimori::API::Client.new(
48
+ # app_name: 'Api Test',
49
+ # aceess_token: '****',
50
+ # refresh_token: '****'
51
+ # )
52
+ # client.v1.animes(page: 2, limit: 20) #=> [{ id: 1, ... }, { id: 2, ... }, ...]
53
+ # @example Get top 50 ongoing anime titles
54
+ # client = Shikimori::API::Client.new(
55
+ # app_name: 'Api Test',
56
+ # aceess_token: '****',
57
+ # refresh_token: '****'
58
+ # )
59
+ # client.v1.animes(limit: 50, status: 'ongoing', order: 'ranked') #=> [{ id: 1, ... }, { id: 2, ... }, ...]
60
+ # @example Get 10 random anime titles released in the 90s
61
+ # client = Shikimori::API::Client.new(
62
+ # app_name: 'Api Test',
63
+ # aceess_token: '****',
64
+ # refresh_token: '****'
65
+ # )
66
+ # client.v1.animes(limit: 10, order: 'random', season: '199x') #=> [{ id: 1, ... }, { id: 2, ... }, ...]
67
+ def animes(headers: nil, **query)
68
+ rest.get base_url.join('animes').url, headers: headers, query: query
69
+ end
70
+
71
+ # Get an anime by id
72
+ #
73
+ # @param id [#to_s] Anime id
74
+ # @param headers [Hash] Request headers
75
+ # @param query [Hash] Query string parameters for request
76
+ #
77
+ # @return [Hash] Hash representing anime
78
+ #
79
+ # @see https://shikimori.one/api/doc/1.0/animes/show Shikimori's API documentation
80
+ # @example Get anime with id equal to 1
81
+ # client = Shikimori::API::Client.new(
82
+ # app_name: 'Api Test',
83
+ # aceess_token: '****',
84
+ # refresh_token: '****'
85
+ # )
86
+ # client.v1.anime(1) #=> { id: 1, ... }
87
+ def anime(id, headers: nil, **query)
88
+ rest.get base_url.join('animes', id.to_s).url, headers: headers, query: query
89
+ end
90
+
91
+ # Get an anime roles
92
+ #
93
+ # @param id [#to_s] Anime id
94
+ # @param headers [Hash] Request headers
95
+ # @param query [Hash] Query string parameters for request
96
+ #
97
+ # @return [Hash] Hash representing anime roles
98
+ #
99
+ # @raise [Shikimori::API::NotFoundError] if anime not exists
100
+ #
101
+ # @see https://shikimori.one/api/doc/1.0/animes/roles Shikimori's API documentation
102
+ # @example Get a first anime roles
103
+ # client = Shikimori::API::Client.new(
104
+ # app_name: 'Api Test',
105
+ # aceess_token: '****',
106
+ # refresh_token: '****'
107
+ # )
108
+ # client.v1.anime_roles(1) #=> { roles: [...], roles_russian: [...], character: {...}, person: {...} }
109
+ def anime_roles(id, headers: nil, **query)
110
+ rest.get base_url.join('animes', id.to_s, 'roles').url, headers: headers, query: query
111
+ end
112
+
113
+ # Get an anime similar
114
+ #
115
+ # @param id [#to_s] Anime id
116
+ # @param headers [Hash] Request headers
117
+ # @param query [Hash] Query string parameters for request
118
+ #
119
+ # @return [Array<Hash>] Array of hashes representing similar animes
120
+ #
121
+ # @raise [Shikimori::API::NotFoundError] if anime not exists
122
+ #
123
+ # @see https://shikimori.one/api/doc/1.0/animes/similar Shikimori's API documentation
124
+ # @example Get a similar anime titles for anime with id equal to 1
125
+ # client = Shikimori::API::Client.new(
126
+ # app_name: 'Api Test',
127
+ # aceess_token: '****',
128
+ # refresh_token: '****'
129
+ # )
130
+ # client.v1.anime_similar(1) #=> { id: 2, ... }
131
+ def anime_similar(id, headers: nil, **query)
132
+ rest.get base_url.join('animes', id.to_s, 'similar').url, headers: headers, query: query
133
+ end
134
+
135
+ # Get an related animes
136
+ #
137
+ # @param id [#to_s] Anime id
138
+ # @param headers [Hash] Request headers
139
+ # @param query [Hash] Query string parameters for request
140
+ #
141
+ # @return [Array<Hash>] Array of hashes representing related animes
142
+ #
143
+ # @raise [Shikimori::API::NotFoundError] if anime not exists
144
+ #
145
+ # @see https://shikimori.one/api/doc/1.0/animes/related Shikimori's API documentation
146
+ # @example Get a related anime, manga and ranobe titles for anime with id equal to 1
147
+ # client = Shikimori::API::Client.new(
148
+ # app_name: 'Api Test',
149
+ # aceess_token: '****',
150
+ # refresh_token: '****'
151
+ # )
152
+ # client.v1.anime_related(1)
153
+ # #=> [{ relation: "...", relation_russian: "...", anime: { id: 3, ... }, manga: { id: 1, ... } }]
154
+ def anime_related(id, headers: nil, **query)
155
+ rest.get base_url.join('animes', id.to_s, 'related').url, headers: headers, query: query
156
+ end
157
+
158
+ # Get an anime screenshots
159
+ #
160
+ # @param id [#to_s] Anime id
161
+ # @param headers [Hash] Request headers
162
+ # @param query [Hash] Query string parameters for request
163
+ #
164
+ # @return [Array<Hash>] Array of hashes representing anime screenshots
165
+ #
166
+ # @raise [Shikimori::API::NotFoundError] if anime not exists
167
+ #
168
+ # @see https://shikimori.one/api/doc/1.0/animes/screenshots Shikimori's API documentation
169
+ # @example Get screenshots for anime with id equal to 1
170
+ # client = Shikimori::API::Client.new(
171
+ # app_name: 'Api Test',
172
+ # aceess_token: '****',
173
+ # refresh_token: '****'
174
+ # )
175
+ # client.v1.anime_screenshots(1) #=> [{ original: "...", preview: "..." }]
176
+ def anime_screenshots(id, headers: nil, **query)
177
+ rest.get base_url.join('animes', id.to_s, 'screenshots').url, headers: headers, query: query
178
+ end
179
+
180
+ # Get an anime franchise
181
+ #
182
+ # @param id [#to_s] Anime id
183
+ # @param headers [Hash] Request headers
184
+ # @param query [Hash] Query string parameters for request
185
+ #
186
+ # @return [Hash] Hash representing of anime's franchise tree
187
+ #
188
+ # @raise [Shikimori::API::NotFoundError] if anime not exists
189
+ #
190
+ # @see https://shikimori.one/api/doc/1.0/animes/franchise Shikimori's API documentation
191
+ # @example Get anime franchise tree for anime with id equal to 1
192
+ # client = Shikimori::API::Client.new(
193
+ # app_name: 'Api Test',
194
+ # aceess_token: '****',
195
+ # refresh_token: '****'
196
+ # )
197
+ # client.v1.anime_franchise(1) #=> { links: [{ id: 1, ... }], nodes: [{ id: 1, ... }], current_id: 1 }
198
+ def anime_franchise(id, headers: nil, **query)
199
+ rest.get base_url.join('animes', id.to_s, 'franchise').url, headers: headers, query: query
200
+ end
201
+
202
+ # Get an anime external links
203
+ #
204
+ # @param id [#to_s] Anime id
205
+ # @param headers [Hash] Request headers
206
+ # @param query [Hash] Query string parameters for request
207
+ #
208
+ # @return [Array<Hash>] Array of hashes representing anime's extenal links
209
+ #
210
+ # @raise [Shikimori::API::NotFoundError] if anime not exists
211
+ #
212
+ # @see https://shikimori.one/api/doc/1.0/animes/external_links Shikimori's API documentation
213
+ # @example Get related external links for anime with id equal 1
214
+ # client = Shikimori::API::Client.new(
215
+ # app_name: 'Api Test',
216
+ # aceess_token: '****',
217
+ # refresh_token: '****'
218
+ # )
219
+ # client.v1.anime_external_links(1) #=> [{ id: 1, ... }, { id: nil, ... }]
220
+ def anime_external_links(id, headers: nil, **query)
221
+ rest.get base_url.join('animes', id.to_s, 'external_links').url, headers: headers, query: query
222
+ end
223
+
224
+ # Get an anime topics
225
+ #
226
+ # @param id [#to_s] Anime id
227
+ # @param headers [Hash] Request headers
228
+ # @param query [Hash] Query string parameters for request
229
+ # @option query [Integer] :page Number of page. Must be between 1 and 100000
230
+ # @option query [Integer] :limit Number of titles per page. Must be a lower or equal that 50
231
+ # @option query ['anons', 'ongoing', 'released', 'episode'] :kind Type of topic
232
+ # @option query [Integer] :episode Number of anime's episode. Required for :kind equal to 'episode'
233
+ #
234
+ # @return [Array<Hash>] Array of hashes representing anime's topics
235
+ #
236
+ # @raise [Shikimori::API::NotFoundError] if anime not exists
237
+ #
238
+ # @see https://shikimori.one/api/doc/1.0/animes/topics Shikimori's API documentation
239
+ # @example Get topics for anime with id equal 1
240
+ # client = Shikimori::API::Client.new(
241
+ # app_name: 'Api Test',
242
+ # aceess_token: '****',
243
+ # refresh_token: '****'
244
+ # )
245
+ # client.v1.anime_topics(1) #=> [{ id: 1, ... }]
246
+ def anime_topics(id, headers: nil, **query)
247
+ rest.get base_url.join('animes', id.to_s, 'topics').url, headers: headers, query: query
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shikimori
4
+ module API
5
+ class V1
6
+ # Methods for the Appears API
7
+ #
8
+ # @see https://shikimori.one/api/doc/1.0/appear Shikimori's API documentation
9
+ module Appear
10
+ # Mark comments or topics as read
11
+ #
12
+ # @param comment_ids [Array<#to_s>] Comment ids
13
+ # @param topic_ids [Array<#to_s>] Topic ids
14
+ # @param headers [Hash] Request headers
15
+ # @param query [Hash] Query string parameters for request
16
+ #
17
+ # @return [Boolean] True if mark comments or topics as read successful, false otherwise.
18
+ #
19
+ # @see https://shikimori.one/api/doc/1.0/appear/create Shikimori's API documentation
20
+ # @example Mark comment 7, 8 and topic 270101 as read
21
+ # client = Shikimori::API::Client.new(
22
+ # app_name: 'Api Test',
23
+ # aceess_token: '****',
24
+ # refresh_token: '****'
25
+ # )
26
+ # client.v1.create_appear(ids: ["comment-7", "comment-8","topic-270101"]) #=> true
27
+ def create_appear(comment_ids: [], topic_ids: [], headers: nil, **query)
28
+ comments = comment_ids.map { "comment-#{_1}" }
29
+ topics = topic_ids.map { "topic-#{_1}" }
30
+
31
+ ids = comments + topics
32
+
33
+ rest.post base_url.join('appear').url, { ids: ids.join(',') }, headers: headers, query: query
34
+
35
+ true
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shikimori
4
+ module API
5
+ class V1
6
+ # Methods for the Bans API
7
+ #
8
+ # @see https://shikimori.one/api/doc/1.0/bans Shikimori's API documentation
9
+ module Bans
10
+ # Get list of bans
11
+ #
12
+ # @param headers [Hash] Request headers
13
+ # @param query [Hash] Query string parameters for request
14
+ #
15
+ # @return [Array<Hash>] Array of hashes representing bans
16
+ #
17
+ # @see https://shikimori.one/api/doc/1.0/bans/index Shikimori's API documentation
18
+ # @example Get list of bans
19
+ # client = Shikimori::API::Client.new(
20
+ # app_name: 'Api Test',
21
+ # aceess_token: '****',
22
+ # refresh_token: '****'
23
+ # )
24
+ # client.v1.bans #=> [{ id: 1, ... }, { id: 2, ... }]
25
+ def bans(headers: nil, **query)
26
+ rest.get base_url.join('bans').url, headers: headers, query: query
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shikimori
4
+ module API
5
+ class V1
6
+ # Methods for the Calendars API
7
+ #
8
+ # @see https://shikimori.one/api/doc/1.0/calendars Shikimori's API documentation
9
+ module Calendars
10
+ # Get a calendar
11
+ #
12
+ # @param headers [Hash] Request headers
13
+ # @param query [Hash] Query string parameters for request
14
+ # @option query [TrueClass, FalseClass] :censored Set to false to allow hentai, yaoi and yuri
15
+ #
16
+ # @return [Array<Hash>] Array of hashes representing calendars
17
+ #
18
+ # @see https://shikimori.one/api/doc/1.0/calendars/show Shikimori's API documentation
19
+ # @example Get a calendar
20
+ # client = Shikimori::API::Client.new(
21
+ # app_name: 'Api Test',
22
+ # aceess_token: '****',
23
+ # refresh_token: '****'
24
+ # )
25
+ # client.v1.calendar #=> [{ next_episode: 1, anime: [{ id: 1, ... }], ... }]
26
+ def calendar(headers: nil, **query)
27
+ rest.get base_url.join('calendar').url, headers: headers, query: query
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shikimori
4
+ module API
5
+ class V1
6
+ # Methods for the Characters API
7
+ #
8
+ # @see https://shikimori.one/api/doc/1.0/characters Shikimori's API documentation
9
+ module Characters
10
+ # Get list of Characters
11
+ #
12
+ # @param headers [Hash] Request headers
13
+ # @param query [Hash] Query string parameters for request
14
+ # @option query [String] :search A character name for searching
15
+ #
16
+ # @return [Array<Hash>] Array of hashes representing characters
17
+ #
18
+ # @see https://shikimori.one/api/doc/1.0/characters/search Shikimori's API documentation
19
+ # @example Search characters
20
+ # client = Shikimori::API::Client.new(
21
+ # app_name: 'Api Test',
22
+ # aceess_token: '****',
23
+ # refresh_token: '****'
24
+ # )
25
+ # client.v1.characters(search: 'asdf') #=> [{ id: 1, ... }]
26
+ def characters(headers: nil, **query)
27
+ rest.get base_url.join('characters', 'search').url, headers: headers, query: query
28
+ end
29
+
30
+ # Get a character by id
31
+ #
32
+ # @param id [#to_s] Character id
33
+ # @param headers [Hash] Request headers
34
+ # @param query [Hash] Query string parameters for request
35
+ #
36
+ # @return [Hash] Hash representing character
37
+ #
38
+ # @see https://shikimori.one/api/doc/1.0/characters/show Shikimori's API documentation
39
+ # @example Get character with id equal to 1
40
+ # client = Shikimori::API::Client.new(
41
+ # app_name: 'Api Test',
42
+ # aceess_token: '****',
43
+ # refresh_token: '****'
44
+ # )
45
+ # client.v1.character(1) #=> { id: 1, ... }
46
+ def character(id, headers: nil, **query)
47
+ rest.get base_url.join('characters', id.to_s).url, headers: headers, query: query
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end