jikanrb 0.2.1 → 0.3.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/CHANGELOG.md +67 -0
- data/README.md +116 -51
- data/lib/jikanrb/client.rb +75 -31
- data/lib/jikanrb/resources/anime_resource.rb +185 -0
- data/lib/jikanrb/resources/base_resource.rb +41 -0
- data/lib/jikanrb/resources/character_resource.rb +82 -0
- data/lib/jikanrb/resources/manga_resource.rb +125 -0
- data/lib/jikanrb/resources/person_resource.rb +82 -0
- data/lib/jikanrb/version.rb +1 -1
- data/lib/jikanrb.rb +15 -8
- metadata +7 -3
- data/.claude/settings.local.json +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cf12793ef80ef81581dbad79ebe5d15266029db927c4e4ab5f741323b84f7d6f
|
|
4
|
+
data.tar.gz: 4c28905ede783f3047996a6c1bb0a74f88a8529b0d76d0658d546c9d89af6164
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1beb1a905b77c37a189dc6dfed33bd42923b412a9eef9aeeb81be74f484df4ed06626ad1209de68a5f92b2a150550c4cc2d234832ad372d616aed56faa8c08c5
|
|
7
|
+
data.tar.gz: e578ca35e574134812424ddb696ac2166e6ea216e7be343bcc5663ccbf10858b56c8d8255f2fab830a250b34c2c57d61133ee14ab45b3231b520e657c07c71c4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.3.0] - 2026-01-31
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Fluent API** for accessing sub-resources with chainable methods
|
|
7
|
+
- `BaseResource` class providing common functionality for all resources
|
|
8
|
+
- `AnimeResource` with 14 sub-resource methods:
|
|
9
|
+
- `info(full: false)` - Basic/full anime details
|
|
10
|
+
- `characters` - Characters and voice actors
|
|
11
|
+
- `staff` - Staff members
|
|
12
|
+
- `episodes(page: nil)` - Episodes with pagination
|
|
13
|
+
- `news` - Related news articles
|
|
14
|
+
- `forum` - Forum topics
|
|
15
|
+
- `videos` - PVs, episodes, music videos
|
|
16
|
+
- `pictures` - Anime pictures
|
|
17
|
+
- `statistics` - User statistics
|
|
18
|
+
- `recommendations` - User recommendations
|
|
19
|
+
- `relations` - Related anime/manga
|
|
20
|
+
- `themes` - Opening/ending themes
|
|
21
|
+
- `external` - External links
|
|
22
|
+
- `streaming` - Streaming platform links
|
|
23
|
+
- `MangaResource` with 9 sub-resource methods:
|
|
24
|
+
- `info(full: false)` - Basic/full manga details
|
|
25
|
+
- `characters` - Characters
|
|
26
|
+
- `news` - Related news articles
|
|
27
|
+
- `forum` - Forum topics
|
|
28
|
+
- `pictures` - Manga pictures
|
|
29
|
+
- `statistics` - User statistics
|
|
30
|
+
- `recommendations` - User recommendations
|
|
31
|
+
- `relations` - Related anime/manga
|
|
32
|
+
- `external` - External links
|
|
33
|
+
- `CharacterResource` with 5 sub-resource methods:
|
|
34
|
+
- `info(full: false)` - Basic/full character details
|
|
35
|
+
- `animes` - Anime appearances
|
|
36
|
+
- `mangas` - Manga appearances
|
|
37
|
+
- `voices` - Voice actors
|
|
38
|
+
- `pictures` - Character pictures
|
|
39
|
+
- `PersonResource` with 5 sub-resource methods:
|
|
40
|
+
- `info(full: false)` - Basic/full person details
|
|
41
|
+
- `animes` - Anime staff positions
|
|
42
|
+
- `mangas` - Manga work
|
|
43
|
+
- `voices` - Voice acting roles
|
|
44
|
+
- `pictures` - Person pictures
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
- `Client#anime(id)` now returns `AnimeResource` instead of `Hash`
|
|
48
|
+
- `Client#manga(id)` now returns `MangaResource` instead of `Hash`
|
|
49
|
+
- `Client#character(id)` now returns `CharacterResource` instead of `Hash`
|
|
50
|
+
- `Client#person(id)` now returns `PersonResource` instead of `Hash`
|
|
51
|
+
|
|
52
|
+
### Breaking Changes
|
|
53
|
+
- Removed `full:` parameter from `anime`, `manga`, `character`, and `person` methods
|
|
54
|
+
- Use `.info` or `.info(full: true)` for the previous behavior:
|
|
55
|
+
```ruby
|
|
56
|
+
# Before (v0.2.x)
|
|
57
|
+
client.anime(1)
|
|
58
|
+
client.anime(1, full: true)
|
|
59
|
+
|
|
60
|
+
# After (v0.3.0+)
|
|
61
|
+
client.anime(1).info
|
|
62
|
+
client.anime(1).info(full: true)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Documentation
|
|
66
|
+
- Complete YARD documentation for all resource classes
|
|
67
|
+
- Updated README with fluent API examples
|
|
68
|
+
- Added migration guide for breaking changes
|
|
69
|
+
|
|
3
70
|
## [0.2.1] - 2026-01-10
|
|
4
71
|
|
|
5
72
|
### Changed
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Jikanrb
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/rb/jikanrb)
|
|
4
|
-
[](https://github.com/sbrocos/jikanrb/actions)
|
|
5
5
|
|
|
6
6
|
A modern Ruby client for the [Jikan API v4](https://jikan.moe/) - the unofficial MyAnimeList API.
|
|
7
7
|
|
|
@@ -10,7 +10,7 @@ A modern Ruby client for the [Jikan API v4](https://jikan.moe/) - the unofficial
|
|
|
10
10
|
Add this line to your application's Gemfile:
|
|
11
11
|
|
|
12
12
|
```ruby
|
|
13
|
-
gem
|
|
13
|
+
gem "jikanrb"
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
And then execute:
|
|
@@ -30,17 +30,14 @@ gem install jikanrb
|
|
|
30
30
|
### Quick Start
|
|
31
31
|
|
|
32
32
|
```ruby
|
|
33
|
-
require
|
|
33
|
+
require "jikanrb"
|
|
34
34
|
|
|
35
|
-
# Get anime
|
|
36
|
-
anime = Jikanrb.anime(1)
|
|
37
|
-
|
|
38
|
-
# Access data using strings or symbols (Indifferent Access)
|
|
39
|
-
puts anime["data"]["title"] # => "Cowboy Bebop"
|
|
40
|
-
puts anime[:data][:title] # => "Cowboy Bebop"
|
|
35
|
+
# Get anime info using fluent API
|
|
36
|
+
anime = Jikanrb.anime(1).info
|
|
37
|
+
puts anime[:data][:title] # => "Cowboy Bebop"
|
|
41
38
|
|
|
42
39
|
# Get full anime info (includes relations, theme songs, etc.)
|
|
43
|
-
anime = Jikanrb.anime(1
|
|
40
|
+
anime = Jikanrb.anime(1).info(full: true)
|
|
44
41
|
|
|
45
42
|
# Search anime
|
|
46
43
|
results = Jikanrb.search_anime("Naruto")
|
|
@@ -57,11 +54,13 @@ client = Jikanrb::Client.new do |config|
|
|
|
57
54
|
config.max_retries = 5
|
|
58
55
|
end
|
|
59
56
|
|
|
60
|
-
#
|
|
61
|
-
client.anime(1)
|
|
62
|
-
client.manga(1)
|
|
63
|
-
client.character(1)
|
|
64
|
-
client.person(1)
|
|
57
|
+
# Fluent API for resources
|
|
58
|
+
client.anime(1).info
|
|
59
|
+
client.manga(1).info
|
|
60
|
+
client.character(1).info
|
|
61
|
+
client.person(1).info
|
|
62
|
+
|
|
63
|
+
# Search and listings
|
|
65
64
|
client.search_anime("One Piece", type: "tv", status: "airing")
|
|
66
65
|
client.top_anime(type: "tv", filter: "bypopularity")
|
|
67
66
|
client.season(2024, "winter")
|
|
@@ -69,19 +68,75 @@ client.season_now
|
|
|
69
68
|
client.schedules(day: "monday")
|
|
70
69
|
```
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
## Fluent API (v1.1.0+)
|
|
72
|
+
|
|
73
|
+
Access sub-resources using the fluent interface for cleaner, chainable code.
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
### Anime
|
|
75
76
|
|
|
76
77
|
```ruby
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
client = Jikanrb::Client.new
|
|
79
|
+
|
|
80
|
+
# Basic and full info
|
|
81
|
+
client.anime(1).info # GET /anime/1
|
|
82
|
+
client.anime(1).info(full: true) # GET /anime/1/full
|
|
83
|
+
|
|
84
|
+
# Sub-resources
|
|
85
|
+
client.anime(1).characters # Characters and voice actors
|
|
86
|
+
client.anime(1).staff # Staff members
|
|
87
|
+
client.anime(1).episodes # Episodes (first page)
|
|
88
|
+
client.anime(1).episodes(page: 2) # Episodes (page 2)
|
|
89
|
+
client.anime(1).news # News articles
|
|
90
|
+
client.anime(1).forum # Forum topics
|
|
91
|
+
client.anime(1).videos # PVs, episodes, music videos
|
|
92
|
+
client.anime(1).pictures # Pictures
|
|
93
|
+
client.anime(1).statistics # User statistics
|
|
94
|
+
client.anime(1).recommendations # User recommendations
|
|
95
|
+
client.anime(1).relations # Related anime/manga
|
|
96
|
+
client.anime(1).themes # Opening/ending themes
|
|
97
|
+
client.anime(1).external # External links
|
|
98
|
+
client.anime(1).streaming # Streaming platform links
|
|
83
99
|
```
|
|
84
100
|
|
|
101
|
+
### Manga
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
client.manga(1).info # GET /manga/1
|
|
105
|
+
client.manga(1).info(full: true) # GET /manga/1/full
|
|
106
|
+
client.manga(1).characters # Characters
|
|
107
|
+
client.manga(1).news # News articles
|
|
108
|
+
client.manga(1).forum # Forum topics
|
|
109
|
+
client.manga(1).pictures # Pictures
|
|
110
|
+
client.manga(1).statistics # User statistics
|
|
111
|
+
client.manga(1).recommendations # User recommendations
|
|
112
|
+
client.manga(1).relations # Related anime/manga
|
|
113
|
+
client.manga(1).external # External links
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Characters
|
|
117
|
+
|
|
118
|
+
```ruby
|
|
119
|
+
client.character(1).info # GET /characters/1
|
|
120
|
+
client.character(1).info(full: true)# GET /characters/1/full
|
|
121
|
+
client.character(1).animes # Anime appearances
|
|
122
|
+
client.character(1).mangas # Manga appearances
|
|
123
|
+
client.character(1).voices # Voice actors
|
|
124
|
+
client.character(1).pictures # Pictures
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### People
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
client.person(1).info # GET /people/1
|
|
131
|
+
client.person(1).info(full: true) # GET /people/1/full
|
|
132
|
+
client.person(1).animes # Anime staff positions
|
|
133
|
+
client.person(1).mangas # Manga work
|
|
134
|
+
client.person(1).voices # Voice acting roles
|
|
135
|
+
client.person(1).pictures # Pictures
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Configuration
|
|
139
|
+
|
|
85
140
|
### Global Configuration
|
|
86
141
|
|
|
87
142
|
```ruby
|
|
@@ -95,14 +150,33 @@ Jikanrb.configure do |config|
|
|
|
95
150
|
end
|
|
96
151
|
```
|
|
97
152
|
|
|
98
|
-
###
|
|
153
|
+
### Rails Configuration
|
|
154
|
+
|
|
155
|
+
Create an initializer (e.g., `config/initializers/jikanrb.rb`):
|
|
156
|
+
|
|
157
|
+
```ruby
|
|
158
|
+
Jikanrb.configure do |config|
|
|
159
|
+
config.read_timeout = 20
|
|
160
|
+
config.max_retries = 3
|
|
161
|
+
config.logger = Rails.logger
|
|
162
|
+
end
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Available Methods
|
|
166
|
+
|
|
167
|
+
### Resource Methods (Fluent API)
|
|
168
|
+
|
|
169
|
+
| Method | Returns | Description |
|
|
170
|
+
| :--- | :--- | :--- |
|
|
171
|
+
| `anime(id)` | `AnimeResource` | Anime resource for sub-resource access |
|
|
172
|
+
| `manga(id)` | `MangaResource` | Manga resource for sub-resource access |
|
|
173
|
+
| `character(id)` | `CharacterResource` | Character resource for sub-resource access |
|
|
174
|
+
| `person(id)` | `PersonResource` | Person resource for sub-resource access |
|
|
175
|
+
|
|
176
|
+
### Direct Methods
|
|
99
177
|
|
|
100
178
|
| Method | Description |
|
|
101
179
|
| :--- | :--- |
|
|
102
|
-
| `anime(id, full: false)` | Get anime by MAL ID |
|
|
103
|
-
| `manga(id, full: false)` | Get manga by MAL ID |
|
|
104
|
-
| `character(id, full: false)` | Get character by MAL ID |
|
|
105
|
-
| `person(id, full: false)` | Get person by MAL ID |
|
|
106
180
|
| `search_anime(query, **params)` | Search anime |
|
|
107
181
|
| `search_manga(query, **params)` | Search manga |
|
|
108
182
|
| `top_anime(type:, filter:, page:)` | Top anime list |
|
|
@@ -111,11 +185,11 @@ end
|
|
|
111
185
|
| `season_now(page:)` | Current season anime |
|
|
112
186
|
| `schedules(day:)` | Weekly schedule |
|
|
113
187
|
|
|
114
|
-
|
|
188
|
+
## Error Handling
|
|
115
189
|
|
|
116
190
|
```ruby
|
|
117
191
|
begin
|
|
118
|
-
anime = Jikanrb.anime(999999999)
|
|
192
|
+
anime = Jikanrb.anime(999999999).info
|
|
119
193
|
rescue Jikanrb::NotFoundError => e
|
|
120
194
|
puts "Anime not found: #{e.message}"
|
|
121
195
|
rescue Jikanrb::RateLimitError => e
|
|
@@ -127,21 +201,22 @@ rescue Jikanrb::Error => e
|
|
|
127
201
|
end
|
|
128
202
|
```
|
|
129
203
|
|
|
130
|
-
|
|
204
|
+
## Pagination
|
|
131
205
|
|
|
132
206
|
The gem provides convenient pagination helpers for working with paginated endpoints:
|
|
133
207
|
|
|
134
208
|
```ruby
|
|
135
|
-
# Automatic pagination - iterates through all pages
|
|
136
209
|
client = Jikanrb::Client.new
|
|
137
|
-
|
|
210
|
+
|
|
211
|
+
# Automatic pagination - iterates through all pages
|
|
212
|
+
paginator = client.paginate(:top_anime, type: "tv")
|
|
138
213
|
|
|
139
214
|
# Get all items (will fetch all pages)
|
|
140
215
|
all_anime = paginator.all
|
|
141
216
|
|
|
142
217
|
# Iterate through all pages lazily
|
|
143
218
|
paginator.each do |anime|
|
|
144
|
-
puts "#{anime[
|
|
219
|
+
puts "#{anime["title"]} - Score: #{anime["score"]}"
|
|
145
220
|
end
|
|
146
221
|
|
|
147
222
|
# Get items from first 3 pages only
|
|
@@ -153,24 +228,15 @@ pagination = client.pagination_info(response)
|
|
|
153
228
|
|
|
154
229
|
puts "Current page: #{pagination.current_page}"
|
|
155
230
|
puts "Total pages: #{pagination.total_pages}"
|
|
156
|
-
puts "Items per page: #{pagination.per_page}"
|
|
157
231
|
puts "Has next page: #{pagination.has_next_page?}"
|
|
158
|
-
puts "Has previous page: #{pagination.has_previous_page?}"
|
|
159
|
-
puts "Next page number: #{pagination.next_page}" if pagination.has_next_page?
|
|
160
232
|
```
|
|
161
233
|
|
|
162
|
-
|
|
234
|
+
## Rate Limiting
|
|
163
235
|
|
|
164
236
|
Jikan API allows **60 requests per minute**. This gem includes automatic retry with exponential backoff for rate limit errors (429).
|
|
165
237
|
|
|
166
238
|
## Development
|
|
167
239
|
|
|
168
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
169
|
-
|
|
170
|
-
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 the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
171
|
-
|
|
172
|
-
### Useful Commands
|
|
173
|
-
|
|
174
240
|
```bash
|
|
175
241
|
# Install dependencies
|
|
176
242
|
bin/setup
|
|
@@ -178,11 +244,14 @@ bin/setup
|
|
|
178
244
|
# Run tests
|
|
179
245
|
bundle exec rspec
|
|
180
246
|
|
|
247
|
+
# Run linter
|
|
248
|
+
bundle exec rubocop
|
|
249
|
+
|
|
181
250
|
# Interactive console
|
|
182
251
|
bin/console
|
|
183
252
|
|
|
184
|
-
#
|
|
185
|
-
bundle exec
|
|
253
|
+
# Generate documentation
|
|
254
|
+
bundle exec yard doc
|
|
186
255
|
```
|
|
187
256
|
|
|
188
257
|
## Acknowledgments
|
|
@@ -191,12 +260,8 @@ This gem is inspired by [jikan.rb](https://github.com/Zerocchi/jikan.rb) by Zero
|
|
|
191
260
|
|
|
192
261
|
## Contributing
|
|
193
262
|
|
|
194
|
-
Bug reports and pull requests are welcome on GitHub at
|
|
263
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/sbrocos/jikanrb.
|
|
195
264
|
|
|
196
265
|
## License
|
|
197
266
|
|
|
198
267
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
199
|
-
|
|
200
|
-
## Code of Conduct
|
|
201
|
-
|
|
202
|
-
Everyone interacting in the Jikanrb project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/jikanrb/blob/main/CODE_OF_CONDUCT.md).
|
data/lib/jikanrb/client.rb
CHANGED
|
@@ -47,44 +47,88 @@ module Jikanrb
|
|
|
47
47
|
request(:get, path, params)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
#
|
|
50
|
+
# Returns an AnimeResource for fluent API access to anime sub-resources
|
|
51
51
|
#
|
|
52
52
|
# @param id [Integer] Anime ID on MyAnimeList
|
|
53
|
-
# @
|
|
54
|
-
#
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
# @return [Resources::AnimeResource] Anime resource for chaining
|
|
54
|
+
#
|
|
55
|
+
# @example Get anime info
|
|
56
|
+
# client.anime(1).info
|
|
57
|
+
# # => { data: { mal_id: 1, title: "Cowboy Bebop", ... } }
|
|
58
|
+
#
|
|
59
|
+
# @example Get full anime info
|
|
60
|
+
# client.anime(1).info(full: true)
|
|
61
|
+
#
|
|
62
|
+
# @example Get anime characters
|
|
63
|
+
# client.anime(1).characters
|
|
64
|
+
#
|
|
65
|
+
# @example Get anime episodes
|
|
66
|
+
# client.anime(1).episodes
|
|
67
|
+
def anime(id)
|
|
68
|
+
Resources::AnimeResource.new(self, id)
|
|
58
69
|
end
|
|
59
70
|
|
|
60
|
-
#
|
|
71
|
+
# Returns a MangaResource for fluent API access to manga sub-resources
|
|
61
72
|
#
|
|
62
73
|
# @param id [Integer] Manga ID on MyAnimeList
|
|
63
|
-
# @
|
|
64
|
-
#
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
# @return [Resources::MangaResource] Manga resource for chaining
|
|
75
|
+
#
|
|
76
|
+
# @example Get manga info
|
|
77
|
+
# client.manga(1).info
|
|
78
|
+
# # => { data: { mal_id: 1, title: "Monster", ... } }
|
|
79
|
+
#
|
|
80
|
+
# @example Get full manga info
|
|
81
|
+
# client.manga(1).info(full: true)
|
|
82
|
+
#
|
|
83
|
+
# @example Get manga characters
|
|
84
|
+
# client.manga(1).characters
|
|
85
|
+
#
|
|
86
|
+
# @example Get manga statistics
|
|
87
|
+
# client.manga(1).statistics
|
|
88
|
+
def manga(id)
|
|
89
|
+
Resources::MangaResource.new(self, id)
|
|
68
90
|
end
|
|
69
91
|
|
|
70
|
-
#
|
|
92
|
+
# Returns a CharacterResource for fluent API access to character sub-resources
|
|
71
93
|
#
|
|
72
94
|
# @param id [Integer] Character ID on MyAnimeList
|
|
73
|
-
# @
|
|
74
|
-
#
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
95
|
+
# @return [Resources::CharacterResource] Character resource for chaining
|
|
96
|
+
#
|
|
97
|
+
# @example Get character info
|
|
98
|
+
# client.character(1).info
|
|
99
|
+
# # => { data: { mal_id: 1, name: "Spike Spiegel", ... } }
|
|
100
|
+
#
|
|
101
|
+
# @example Get full character info
|
|
102
|
+
# client.character(1).info(full: true)
|
|
103
|
+
#
|
|
104
|
+
# @example Get character's anime appearances
|
|
105
|
+
# client.character(1).animes
|
|
106
|
+
#
|
|
107
|
+
# @example Get character's voice actors
|
|
108
|
+
# client.character(1).voices
|
|
109
|
+
def character(id)
|
|
110
|
+
Resources::CharacterResource.new(self, id)
|
|
78
111
|
end
|
|
79
112
|
|
|
80
|
-
#
|
|
113
|
+
# Returns a PersonResource for fluent API access to person sub-resources
|
|
81
114
|
#
|
|
82
115
|
# @param id [Integer] Person ID on MyAnimeList
|
|
83
|
-
# @
|
|
84
|
-
#
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
116
|
+
# @return [Resources::PersonResource] Person resource for chaining
|
|
117
|
+
#
|
|
118
|
+
# @example Get person info
|
|
119
|
+
# client.person(1).info
|
|
120
|
+
# # => { data: { mal_id: 1, name: "Tomokazu Seki", ... } }
|
|
121
|
+
#
|
|
122
|
+
# @example Get full person info
|
|
123
|
+
# client.person(1).info(full: true)
|
|
124
|
+
#
|
|
125
|
+
# @example Get person's anime staff positions
|
|
126
|
+
# client.person(1).animes
|
|
127
|
+
#
|
|
128
|
+
# @example Get person's voice acting roles
|
|
129
|
+
# client.person(1).voices
|
|
130
|
+
def person(id)
|
|
131
|
+
Resources::PersonResource.new(self, id)
|
|
88
132
|
end
|
|
89
133
|
|
|
90
134
|
# Search anime
|
|
@@ -93,7 +137,7 @@ module Jikanrb
|
|
|
93
137
|
# @param params [Hash] Additional filters (type, score, status, etc.)
|
|
94
138
|
# @return [Hash] Search results
|
|
95
139
|
def search_anime(query, **params)
|
|
96
|
-
get('
|
|
140
|
+
get('anime', params.merge(q: query))
|
|
97
141
|
end
|
|
98
142
|
|
|
99
143
|
# Search manga
|
|
@@ -102,7 +146,7 @@ module Jikanrb
|
|
|
102
146
|
# @param params [Hash] Additional filters
|
|
103
147
|
# @return [Hash] Search results
|
|
104
148
|
def search_manga(query, **params)
|
|
105
|
-
get('
|
|
149
|
+
get('manga', params.merge(q: query))
|
|
106
150
|
end
|
|
107
151
|
|
|
108
152
|
# Top anime
|
|
@@ -115,7 +159,7 @@ module Jikanrb
|
|
|
115
159
|
params = { page: page }
|
|
116
160
|
params[:type] = type if type
|
|
117
161
|
params[:filter] = filter if filter
|
|
118
|
-
get('
|
|
162
|
+
get('top/anime', params)
|
|
119
163
|
end
|
|
120
164
|
|
|
121
165
|
# Top manga
|
|
@@ -128,7 +172,7 @@ module Jikanrb
|
|
|
128
172
|
params = { page: page }
|
|
129
173
|
params[:type] = type if type
|
|
130
174
|
params[:filter] = filter if filter
|
|
131
|
-
get('
|
|
175
|
+
get('top/manga', params)
|
|
132
176
|
end
|
|
133
177
|
|
|
134
178
|
# Seasonal anime
|
|
@@ -138,7 +182,7 @@ module Jikanrb
|
|
|
138
182
|
# @param page [Integer] Page number
|
|
139
183
|
# @return [Hash] Seasonal anime
|
|
140
184
|
def season(year, season, page: 1)
|
|
141
|
-
get("
|
|
185
|
+
get("seasons/#{year}/#{season}", page: page)
|
|
142
186
|
end
|
|
143
187
|
|
|
144
188
|
# Current season
|
|
@@ -146,7 +190,7 @@ module Jikanrb
|
|
|
146
190
|
# @param page [Integer] Page number
|
|
147
191
|
# @return [Hash] Current season anime
|
|
148
192
|
def season_now(page: 1)
|
|
149
|
-
get('
|
|
193
|
+
get('seasons/now', page: page)
|
|
150
194
|
end
|
|
151
195
|
|
|
152
196
|
# Weekly schedule
|
|
@@ -154,7 +198,7 @@ module Jikanrb
|
|
|
154
198
|
# @param day [String, nil] Day: "monday", "tuesday", etc.
|
|
155
199
|
# @return [Hash] Anime schedule
|
|
156
200
|
def schedules(day: nil)
|
|
157
|
-
path = day ? "
|
|
201
|
+
path = day ? "schedules/#{day}" : 'schedules'
|
|
158
202
|
get(path)
|
|
159
203
|
end
|
|
160
204
|
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jikanrb
|
|
4
|
+
module Resources
|
|
5
|
+
# Resource class for accessing Anime sub-resources from the Jikan API.
|
|
6
|
+
# Provides fluent API access to anime details, characters, staff, episodes,
|
|
7
|
+
# news, forum topics, videos, pictures, statistics, and more.
|
|
8
|
+
#
|
|
9
|
+
# @example Basic usage
|
|
10
|
+
# client = Jikanrb::Client.new
|
|
11
|
+
# anime = client.anime(1)
|
|
12
|
+
# anime.info # GET /anime/1
|
|
13
|
+
# anime.info(full: true) # GET /anime/1/full
|
|
14
|
+
# anime.characters # GET /anime/1/characters
|
|
15
|
+
# anime.episodes # GET /anime/1/episodes
|
|
16
|
+
#
|
|
17
|
+
# @see https://docs.api.jikan.moe/#tag/anime
|
|
18
|
+
class AnimeResource < BaseResource
|
|
19
|
+
# Returns anime details
|
|
20
|
+
#
|
|
21
|
+
# @param full [Boolean] If true, returns extended information including
|
|
22
|
+
# relations, themes, external links, and streaming links
|
|
23
|
+
# @return [Hash] Anime data as IndifferentHash
|
|
24
|
+
#
|
|
25
|
+
# @example Get basic info
|
|
26
|
+
# client.anime(1).info
|
|
27
|
+
# # => { data: { mal_id: 1, title: "Cowboy Bebop", ... } }
|
|
28
|
+
#
|
|
29
|
+
# @example Get full info
|
|
30
|
+
# client.anime(1).info(full: true)
|
|
31
|
+
# # => { data: { mal_id: 1, title: "...", relations: [...], themes: {...} } }
|
|
32
|
+
def info(full: false)
|
|
33
|
+
path = full ? "anime/#{@id}/full" : "anime/#{@id}"
|
|
34
|
+
get(path)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns characters and their voice actors for this anime
|
|
38
|
+
#
|
|
39
|
+
# @return [Hash] List of characters as IndifferentHash
|
|
40
|
+
#
|
|
41
|
+
# @example
|
|
42
|
+
# client.anime(1).characters
|
|
43
|
+
# # => { data: [{ character: { mal_id: 1, name: "Spike Spiegel" }, role: "Main", voice_actors: [...] }, ...] }
|
|
44
|
+
def characters
|
|
45
|
+
get("anime/#{@id}/characters")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns staff members for this anime
|
|
49
|
+
#
|
|
50
|
+
# @return [Hash] List of staff as IndifferentHash
|
|
51
|
+
#
|
|
52
|
+
# @example
|
|
53
|
+
# client.anime(1).staff
|
|
54
|
+
# # => { data: [{ person: { mal_id: 1, name: "..." }, positions: ["Director"] }, ...] }
|
|
55
|
+
def staff
|
|
56
|
+
get("anime/#{@id}/staff")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Returns episodes for this anime
|
|
60
|
+
#
|
|
61
|
+
# @param page [Integer, nil] Page number for pagination
|
|
62
|
+
# @return [Hash] List of episodes as IndifferentHash
|
|
63
|
+
#
|
|
64
|
+
# @example Get first page of episodes
|
|
65
|
+
# client.anime(1).episodes
|
|
66
|
+
# # => { data: [{ mal_id: 1, title: "Asteroid Blues", ... }, ...], pagination: { ... } }
|
|
67
|
+
#
|
|
68
|
+
# @example Get specific page
|
|
69
|
+
# client.anime(1).episodes(page: 2)
|
|
70
|
+
def episodes(page: nil)
|
|
71
|
+
get("anime/#{@id}/episodes", { page: page }.compact)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Returns news articles related to this anime
|
|
75
|
+
#
|
|
76
|
+
# @return [Hash] List of news articles as IndifferentHash
|
|
77
|
+
#
|
|
78
|
+
# @example
|
|
79
|
+
# client.anime(1).news
|
|
80
|
+
# # => { data: [{ mal_id: 1, title: "...", date: "...", author_username: "..." }, ...] }
|
|
81
|
+
def news
|
|
82
|
+
get("anime/#{@id}/news")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Returns forum topics related to this anime
|
|
86
|
+
#
|
|
87
|
+
# @return [Hash] List of forum topics as IndifferentHash
|
|
88
|
+
#
|
|
89
|
+
# @example
|
|
90
|
+
# client.anime(1).forum
|
|
91
|
+
# # => { data: [{ mal_id: 1, title: "...", date: "...", author_username: "..." }, ...] }
|
|
92
|
+
def forum
|
|
93
|
+
get("anime/#{@id}/forum")
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Returns videos (PVs, episodes, music videos) for this anime
|
|
97
|
+
#
|
|
98
|
+
# @return [Hash] Video data as IndifferentHash
|
|
99
|
+
#
|
|
100
|
+
# @example
|
|
101
|
+
# client.anime(1).videos
|
|
102
|
+
# # => { data: { promo: [...], episodes: [...], music_videos: [...] } }
|
|
103
|
+
def videos
|
|
104
|
+
get("anime/#{@id}/videos")
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Returns pictures of this anime
|
|
108
|
+
#
|
|
109
|
+
# @return [Hash] List of pictures as IndifferentHash
|
|
110
|
+
#
|
|
111
|
+
# @example
|
|
112
|
+
# client.anime(1).pictures
|
|
113
|
+
# # => { data: [{ jpg: { image_url: "https://..." }, webp: { ... } }, ...] }
|
|
114
|
+
def pictures
|
|
115
|
+
get("anime/#{@id}/pictures")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Returns statistics for this anime
|
|
119
|
+
#
|
|
120
|
+
# @return [Hash] Statistics data as IndifferentHash
|
|
121
|
+
#
|
|
122
|
+
# @example
|
|
123
|
+
# client.anime(1).statistics
|
|
124
|
+
# # => { data: { watching: 12345, completed: 67890, on_hold: 1234, ... } }
|
|
125
|
+
def statistics
|
|
126
|
+
get("anime/#{@id}/statistics")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Returns user recommendations for this anime
|
|
130
|
+
#
|
|
131
|
+
# @return [Hash] List of recommendations as IndifferentHash
|
|
132
|
+
#
|
|
133
|
+
# @example
|
|
134
|
+
# client.anime(1).recommendations
|
|
135
|
+
# # => { data: [{ entry: { mal_id: 5, title: "..." }, votes: 123 }, ...] }
|
|
136
|
+
def recommendations
|
|
137
|
+
get("anime/#{@id}/recommendations")
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Returns related anime/manga entries
|
|
141
|
+
#
|
|
142
|
+
# @return [Hash] List of relations as IndifferentHash
|
|
143
|
+
#
|
|
144
|
+
# @example
|
|
145
|
+
# client.anime(1).relations
|
|
146
|
+
# # => { data: [{ relation: "Adaptation", entry: [{ mal_id: 173, type: "manga", name: "..." }] }, ...] }
|
|
147
|
+
def relations
|
|
148
|
+
get("anime/#{@id}/relations")
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Returns opening and ending themes for this anime
|
|
152
|
+
#
|
|
153
|
+
# @return [Hash] Theme songs as IndifferentHash
|
|
154
|
+
#
|
|
155
|
+
# @example
|
|
156
|
+
# client.anime(1).themes
|
|
157
|
+
# # => { data: { openings: ["Tank! by The Seatbelts"], endings: ["The Real Folk Blues by ..."] } }
|
|
158
|
+
def themes
|
|
159
|
+
get("anime/#{@id}/themes")
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Returns external links for this anime
|
|
163
|
+
#
|
|
164
|
+
# @return [Hash] List of external links as IndifferentHash
|
|
165
|
+
#
|
|
166
|
+
# @example
|
|
167
|
+
# client.anime(1).external
|
|
168
|
+
# # => { data: [{ name: "Official Site", url: "https://..." }, ...] }
|
|
169
|
+
def external
|
|
170
|
+
get("anime/#{@id}/external")
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Returns streaming links for this anime
|
|
174
|
+
#
|
|
175
|
+
# @return [Hash] List of streaming platforms as IndifferentHash
|
|
176
|
+
#
|
|
177
|
+
# @example
|
|
178
|
+
# client.anime(1).streaming
|
|
179
|
+
# # => { data: [{ name: "Crunchyroll", url: "https://..." }, ...] }
|
|
180
|
+
def streaming
|
|
181
|
+
get("anime/#{@id}/streaming")
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jikanrb
|
|
4
|
+
module Resources
|
|
5
|
+
# Base class for all resource classes.
|
|
6
|
+
# Provides common functionality for accessing sub-resources from the Jikan API.
|
|
7
|
+
#
|
|
8
|
+
# @abstract Subclass and implement specific resource methods
|
|
9
|
+
#
|
|
10
|
+
# @example Creating a custom resource
|
|
11
|
+
# class AnimeResource < BaseResource
|
|
12
|
+
# def characters
|
|
13
|
+
# get("anime/#{@id}/characters")
|
|
14
|
+
# end
|
|
15
|
+
# end
|
|
16
|
+
class BaseResource
|
|
17
|
+
# @return [Integer] The resource ID
|
|
18
|
+
attr_reader :id
|
|
19
|
+
|
|
20
|
+
# Creates a new resource instance
|
|
21
|
+
#
|
|
22
|
+
# @param client [Jikanrb::Client] The client instance to use for requests
|
|
23
|
+
# @param id [Integer] The resource ID on MyAnimeList
|
|
24
|
+
def initialize(client, id)
|
|
25
|
+
@client = client
|
|
26
|
+
@id = id
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
# Performs a GET request through the client
|
|
32
|
+
#
|
|
33
|
+
# @param path [String] The API endpoint path
|
|
34
|
+
# @param params [Hash] Optional query parameters
|
|
35
|
+
# @return [Hash] The API response as an IndifferentHash
|
|
36
|
+
def get(path, params = {})
|
|
37
|
+
@client.send(:request, :get, path, params)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jikanrb
|
|
4
|
+
module Resources
|
|
5
|
+
# Resource class for accessing Character sub-resources from the Jikan API.
|
|
6
|
+
# Provides fluent API access to character details, anime appearances,
|
|
7
|
+
# manga appearances, voice actors, and pictures.
|
|
8
|
+
#
|
|
9
|
+
# @example Basic usage
|
|
10
|
+
# client = Jikanrb::Client.new
|
|
11
|
+
# character = client.character(1)
|
|
12
|
+
# character.info # GET /characters/1
|
|
13
|
+
# character.info(full: true) # GET /characters/1/full
|
|
14
|
+
# character.anime # GET /characters/1/anime
|
|
15
|
+
# character.voices # GET /characters/1/voices
|
|
16
|
+
#
|
|
17
|
+
# @see https://docs.api.jikan.moe/#tag/characters
|
|
18
|
+
class CharacterResource < BaseResource
|
|
19
|
+
# Returns character details
|
|
20
|
+
#
|
|
21
|
+
# @param full [Boolean] If true, returns extended information including
|
|
22
|
+
# anime appearances, manga appearances, and voice actors
|
|
23
|
+
# @return [Hash] Character data as IndifferentHash
|
|
24
|
+
#
|
|
25
|
+
# @example Get basic info
|
|
26
|
+
# client.character(1).info
|
|
27
|
+
# # => { data: { mal_id: 1, name: "Spike Spiegel", ... } }
|
|
28
|
+
#
|
|
29
|
+
# @example Get full info
|
|
30
|
+
# client.character(1).info(full: true)
|
|
31
|
+
# # => { data: { mal_id: 1, name: "...", anime: [...], voices: [...] } }
|
|
32
|
+
def info(full: false)
|
|
33
|
+
path = full ? "characters/#{@id}/full" : "characters/#{@id}"
|
|
34
|
+
get(path)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns anime appearances for this character
|
|
38
|
+
#
|
|
39
|
+
# @return [Hash] List of anime appearances as IndifferentHash
|
|
40
|
+
#
|
|
41
|
+
# @example
|
|
42
|
+
# client.character(1).anime
|
|
43
|
+
# # => { data: [{ role: "Main", anime: { mal_id: 1, title: "..." } }, ...] }
|
|
44
|
+
def animes
|
|
45
|
+
get("characters/#{@id}/anime")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns manga appearances for this character
|
|
49
|
+
#
|
|
50
|
+
# @return [Hash] List of manga appearances as IndifferentHash
|
|
51
|
+
#
|
|
52
|
+
# @example
|
|
53
|
+
# client.character(1).manga
|
|
54
|
+
# # => { data: [{ role: "Main", manga: { mal_id: 1, title: "..." } }, ...] }
|
|
55
|
+
def mangas
|
|
56
|
+
get("characters/#{@id}/manga")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Returns voice actors for this character
|
|
60
|
+
#
|
|
61
|
+
# @return [Hash] List of voice actors as IndifferentHash
|
|
62
|
+
#
|
|
63
|
+
# @example
|
|
64
|
+
# client.character(1).voices
|
|
65
|
+
# # => { data: [{ language: "Japanese", person: { mal_id: 11, name: "..." } }, ...] }
|
|
66
|
+
def voices
|
|
67
|
+
get("characters/#{@id}/voices")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Returns pictures of this character
|
|
71
|
+
#
|
|
72
|
+
# @return [Hash] List of pictures as IndifferentHash
|
|
73
|
+
#
|
|
74
|
+
# @example
|
|
75
|
+
# client.character(1).pictures
|
|
76
|
+
# # => { data: [{ jpg: { image_url: "https://..." } }, ...] }
|
|
77
|
+
def pictures
|
|
78
|
+
get("characters/#{@id}/pictures")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jikanrb
|
|
4
|
+
module Resources
|
|
5
|
+
# Resource class for accessing Manga sub-resources from the Jikan API.
|
|
6
|
+
# Provides fluent API access to manga details, characters, news,
|
|
7
|
+
# forum topics, pictures, statistics, and more.
|
|
8
|
+
#
|
|
9
|
+
# @example Basic usage
|
|
10
|
+
# client = Jikanrb::Client.new
|
|
11
|
+
# manga = client.manga(1)
|
|
12
|
+
# manga.info # GET /manga/1
|
|
13
|
+
# manga.info(full: true) # GET /manga/1/full
|
|
14
|
+
# manga.characters # GET /manga/1/characters
|
|
15
|
+
#
|
|
16
|
+
# @see https://docs.api.jikan.moe/#tag/manga
|
|
17
|
+
class MangaResource < BaseResource
|
|
18
|
+
# Returns manga details
|
|
19
|
+
#
|
|
20
|
+
# @param full [Boolean] If true, returns extended information including
|
|
21
|
+
# relations, external links, etc.
|
|
22
|
+
# @return [Hash] Manga data as IndifferentHash
|
|
23
|
+
#
|
|
24
|
+
# @example Get basic info
|
|
25
|
+
# client.manga(1).info
|
|
26
|
+
# # => { data: { mal_id: 1, title: "Monster", ... } }
|
|
27
|
+
#
|
|
28
|
+
# @example Get full info
|
|
29
|
+
# client.manga(1).info(full: true)
|
|
30
|
+
# # => { data: { mal_id: 1, title: "...", relations: [...], external: [...] } }
|
|
31
|
+
def info(full: false)
|
|
32
|
+
path = full ? "manga/#{@id}/full" : "manga/#{@id}"
|
|
33
|
+
get(path)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Returns characters for this manga
|
|
37
|
+
#
|
|
38
|
+
# @return [Hash] List of characters as IndifferentHash
|
|
39
|
+
#
|
|
40
|
+
# @example
|
|
41
|
+
# client.manga(1).characters
|
|
42
|
+
# # => { data: [{ character: { mal_id: 1, name: "Kenzou Tenma" }, role: "Main" }, ...] }
|
|
43
|
+
def characters
|
|
44
|
+
get("manga/#{@id}/characters")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Returns news articles related to this manga
|
|
48
|
+
#
|
|
49
|
+
# @return [Hash] List of news articles as IndifferentHash
|
|
50
|
+
#
|
|
51
|
+
# @example
|
|
52
|
+
# client.manga(1).news
|
|
53
|
+
# # => { data: [{ mal_id: 1, title: "...", date: "...", author_username: "..." }, ...] }
|
|
54
|
+
def news
|
|
55
|
+
get("manga/#{@id}/news")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Returns forum topics related to this manga
|
|
59
|
+
#
|
|
60
|
+
# @return [Hash] List of forum topics as IndifferentHash
|
|
61
|
+
#
|
|
62
|
+
# @example
|
|
63
|
+
# client.manga(1).forum
|
|
64
|
+
# # => { data: [{ mal_id: 1, title: "...", date: "...", author_username: "..." }, ...] }
|
|
65
|
+
def forum
|
|
66
|
+
get("manga/#{@id}/forum")
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Returns pictures of this manga
|
|
70
|
+
#
|
|
71
|
+
# @return [Hash] List of pictures as IndifferentHash
|
|
72
|
+
#
|
|
73
|
+
# @example
|
|
74
|
+
# client.manga(1).pictures
|
|
75
|
+
# # => { data: [{ jpg: { image_url: "https://..." }, webp: { ... } }, ...] }
|
|
76
|
+
def pictures
|
|
77
|
+
get("manga/#{@id}/pictures")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Returns statistics for this manga
|
|
81
|
+
#
|
|
82
|
+
# @return [Hash] Statistics data as IndifferentHash
|
|
83
|
+
#
|
|
84
|
+
# @example
|
|
85
|
+
# client.manga(1).statistics
|
|
86
|
+
# # => { data: { reading: 12345, completed: 67890, on_hold: 1234, ... } }
|
|
87
|
+
def statistics
|
|
88
|
+
get("manga/#{@id}/statistics")
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Returns user recommendations for this manga
|
|
92
|
+
#
|
|
93
|
+
# @return [Hash] List of recommendations as IndifferentHash
|
|
94
|
+
#
|
|
95
|
+
# @example
|
|
96
|
+
# client.manga(1).recommendations
|
|
97
|
+
# # => { data: [{ entry: { mal_id: 5, title: "..." }, votes: 123 }, ...] }
|
|
98
|
+
def recommendations
|
|
99
|
+
get("manga/#{@id}/recommendations")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Returns related anime/manga entries
|
|
103
|
+
#
|
|
104
|
+
# @return [Hash] List of relations as IndifferentHash
|
|
105
|
+
#
|
|
106
|
+
# @example
|
|
107
|
+
# client.manga(1).relations
|
|
108
|
+
# # => { data: [{ relation: "Adaptation", entry: [{ mal_id: 19, type: "anime", name: "..." }] }, ...] }
|
|
109
|
+
def relations
|
|
110
|
+
get("manga/#{@id}/relations")
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Returns external links for this manga
|
|
114
|
+
#
|
|
115
|
+
# @return [Hash] List of external links as IndifferentHash
|
|
116
|
+
#
|
|
117
|
+
# @example
|
|
118
|
+
# client.manga(1).external
|
|
119
|
+
# # => { data: [{ name: "Official Site", url: "https://..." }, ...] }
|
|
120
|
+
def external
|
|
121
|
+
get("manga/#{@id}/external")
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jikanrb
|
|
4
|
+
module Resources
|
|
5
|
+
# Resource class for accessing Person sub-resources from the Jikan API.
|
|
6
|
+
# Provides fluent API access to person details, anime staff positions,
|
|
7
|
+
# manga work, voice acting roles, and pictures.
|
|
8
|
+
#
|
|
9
|
+
# @example Basic usage
|
|
10
|
+
# client = Jikanrb::Client.new
|
|
11
|
+
# person = client.person(1)
|
|
12
|
+
# person.info # GET /people/1
|
|
13
|
+
# person.info(full: true) # GET /people/1/full
|
|
14
|
+
# person.animes # GET /people/1/anime
|
|
15
|
+
# person.voices # GET /people/1/voices
|
|
16
|
+
#
|
|
17
|
+
# @see https://docs.api.jikan.moe/#tag/people
|
|
18
|
+
class PersonResource < BaseResource
|
|
19
|
+
# Returns person details
|
|
20
|
+
#
|
|
21
|
+
# @param full [Boolean] If true, returns extended information including
|
|
22
|
+
# anime, manga, and voice acting roles
|
|
23
|
+
# @return [Hash] Person data as IndifferentHash
|
|
24
|
+
#
|
|
25
|
+
# @example Get basic info
|
|
26
|
+
# client.person(1).info
|
|
27
|
+
# # => { data: { mal_id: 1, name: "Tomokazu Seki", ... } }
|
|
28
|
+
#
|
|
29
|
+
# @example Get full info
|
|
30
|
+
# client.person(1).info(full: true)
|
|
31
|
+
# # => { data: { mal_id: 1, name: "...", anime: [...], voices: [...] } }
|
|
32
|
+
def info(full: false)
|
|
33
|
+
path = full ? "people/#{@id}/full" : "people/#{@id}"
|
|
34
|
+
get(path)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns anime staff positions for this person
|
|
38
|
+
#
|
|
39
|
+
# @return [Hash] List of anime staff positions as IndifferentHash
|
|
40
|
+
#
|
|
41
|
+
# @example
|
|
42
|
+
# client.person(1).animes
|
|
43
|
+
# # => { data: [{ position: "Director", anime: { mal_id: 1, title: "..." } }, ...] }
|
|
44
|
+
def animes
|
|
45
|
+
get("people/#{@id}/anime")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns manga work positions for this person
|
|
49
|
+
#
|
|
50
|
+
# @return [Hash] List of manga work positions as IndifferentHash
|
|
51
|
+
#
|
|
52
|
+
# @example
|
|
53
|
+
# client.person(1).mangas
|
|
54
|
+
# # => { data: [{ position: "Story & Art", manga: { mal_id: 1, title: "..." } }, ...] }
|
|
55
|
+
def mangas
|
|
56
|
+
get("people/#{@id}/manga")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Returns voice acting roles for this person
|
|
60
|
+
#
|
|
61
|
+
# @return [Hash] List of voice acting roles as IndifferentHash
|
|
62
|
+
#
|
|
63
|
+
# @example
|
|
64
|
+
# client.person(1).voices
|
|
65
|
+
# # => { data: [{ role: "Main", character: { ... }, anime: { ... } }, ...] }
|
|
66
|
+
def voices
|
|
67
|
+
get("people/#{@id}/voices")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Returns pictures of this person
|
|
71
|
+
#
|
|
72
|
+
# @return [Hash] List of pictures as IndifferentHash
|
|
73
|
+
#
|
|
74
|
+
# @example
|
|
75
|
+
# client.person(1).pictures
|
|
76
|
+
# # => { data: [{ jpg: { image_url: "https://..." } }, ...] }
|
|
77
|
+
def pictures
|
|
78
|
+
get("people/#{@id}/pictures")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
data/lib/jikanrb/version.rb
CHANGED
data/lib/jikanrb.rb
CHANGED
|
@@ -7,6 +7,13 @@ require_relative 'jikanrb/pagination'
|
|
|
7
7
|
require_relative 'jikanrb/client'
|
|
8
8
|
require_relative 'jikanrb/utils'
|
|
9
9
|
|
|
10
|
+
# Resources module - Fluent API for accessing sub-resources
|
|
11
|
+
require_relative 'jikanrb/resources/base_resource'
|
|
12
|
+
require_relative 'jikanrb/resources/anime_resource'
|
|
13
|
+
require_relative 'jikanrb/resources/manga_resource'
|
|
14
|
+
require_relative 'jikanrb/resources/character_resource'
|
|
15
|
+
require_relative 'jikanrb/resources/person_resource'
|
|
16
|
+
|
|
10
17
|
# Jikanrb is a modern Ruby wrapper for the Jikan REST API v4.
|
|
11
18
|
# Provides easy access to anime, manga, characters, and more from MyAnimeList.
|
|
12
19
|
#
|
|
@@ -69,23 +76,23 @@ module Jikanrb
|
|
|
69
76
|
# Allows using Jikanrb.anime(1) directly
|
|
70
77
|
|
|
71
78
|
# @see Client#anime
|
|
72
|
-
def anime(id
|
|
73
|
-
client.anime(id
|
|
79
|
+
def anime(id)
|
|
80
|
+
client.anime(id)
|
|
74
81
|
end
|
|
75
82
|
|
|
76
83
|
# @see Client#manga
|
|
77
|
-
def manga(id
|
|
78
|
-
client.manga(id
|
|
84
|
+
def manga(id)
|
|
85
|
+
client.manga(id)
|
|
79
86
|
end
|
|
80
87
|
|
|
81
88
|
# @see Client#character
|
|
82
|
-
def character(id
|
|
83
|
-
client.character(id
|
|
89
|
+
def character(id)
|
|
90
|
+
client.character(id)
|
|
84
91
|
end
|
|
85
92
|
|
|
86
93
|
# @see Client#person
|
|
87
|
-
def person(id
|
|
88
|
-
client.person(id
|
|
94
|
+
def person(id)
|
|
95
|
+
client.person(id)
|
|
89
96
|
end
|
|
90
97
|
|
|
91
98
|
# @see Client#search_anime
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jikanrb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sergio Brocos
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01
|
|
11
|
+
date: 2026-02-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -58,7 +58,6 @@ executables: []
|
|
|
58
58
|
extensions: []
|
|
59
59
|
extra_rdoc_files: []
|
|
60
60
|
files:
|
|
61
|
-
- ".claude/settings.local.json"
|
|
62
61
|
- ".ruby-version"
|
|
63
62
|
- CHANGELOG.md
|
|
64
63
|
- CODE_OF_CONDUCT.md
|
|
@@ -70,6 +69,11 @@ files:
|
|
|
70
69
|
- lib/jikanrb/configuration.rb
|
|
71
70
|
- lib/jikanrb/errors.rb
|
|
72
71
|
- lib/jikanrb/pagination.rb
|
|
72
|
+
- lib/jikanrb/resources/anime_resource.rb
|
|
73
|
+
- lib/jikanrb/resources/base_resource.rb
|
|
74
|
+
- lib/jikanrb/resources/character_resource.rb
|
|
75
|
+
- lib/jikanrb/resources/manga_resource.rb
|
|
76
|
+
- lib/jikanrb/resources/person_resource.rb
|
|
73
77
|
- lib/jikanrb/utils.rb
|
|
74
78
|
- lib/jikanrb/version.rb
|
|
75
79
|
- sig/jikanrb.rbs
|