mangadex 5.3.2 → 5.3.3.3
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/Gemfile.lock +2 -2
- data/bin/console +4 -3
- data/docs/authentication.md +226 -0
- data/docs/context.md +93 -0
- data/lib/config.rb +50 -0
- data/lib/errors.rb +42 -0
- data/lib/mangadex/README.md +6 -2
- data/lib/mangadex/api/response.rb +13 -2
- data/lib/mangadex/api/user.rb +51 -7
- data/lib/mangadex/api/version_checker.rb +1 -1
- data/lib/mangadex/api.rb +0 -1
- data/lib/mangadex/artist.rb +20 -1
- data/lib/mangadex/auth.rb +42 -13
- data/lib/mangadex/author.rb +11 -1
- data/lib/mangadex/chapter.rb +11 -0
- data/lib/mangadex/content_rating.rb +6 -1
- data/lib/mangadex/cover_art.rb +11 -0
- data/lib/mangadex/custom_list.rb +20 -0
- data/lib/mangadex/internal/context.rb +141 -0
- data/lib/mangadex/internal/definition.rb +13 -0
- data/lib/mangadex/internal/request.rb +29 -10
- data/lib/mangadex/internal/with_attributes.rb +11 -2
- data/lib/mangadex/internal.rb +1 -0
- data/lib/mangadex/manga.rb +25 -3
- data/lib/mangadex/relationship.rb +35 -13
- data/lib/mangadex/scanlation_group.rb +7 -0
- data/lib/mangadex/sorbet.rb +1 -1
- data/lib/mangadex/storage/basic.rb +18 -0
- data/lib/mangadex/storage/memory.rb +23 -0
- data/lib/mangadex/storage/none.rb +9 -0
- data/lib/mangadex/storage.rb +3 -0
- data/lib/mangadex/tag.rb +5 -0
- data/lib/mangadex/upload.rb +10 -0
- data/lib/mangadex/user.rb +9 -2
- data/lib/mangadex/version.rb +2 -2
- data/lib/mangadex.rb +25 -12
- metadata +11 -3
- data/lib/mangadex/api/context.rb +0 -63
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: aa7f120a4bf9d6aece81c094b3a3926d104f280cdc00f8d057e30511c66d6e0c
|
|
4
|
+
data.tar.gz: 99f011001e634a143b8e186098f788b581f58e396e2e04b332ac8a896c5faaf4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '08679f0eb4fbaf40a0797db0ad7d8f42f329d5dcbdb121a48ce125a225258cb465de74e6b335204a05bf87817f6d8b4ab3c0db8efbb4980521c9d14a2b35079a'
|
|
7
|
+
data.tar.gz: a977bc36cf961c1ebc320e4d8ca0a4c6d32fcf5aa058b6461d04d4420b0c89c279db5ecada7ea5f61fe24010e943cb293ff768ee4772d2d23c0a7a0b26dbdbdd
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
mangadex (5.3.
|
|
4
|
+
mangadex (5.3.3.2)
|
|
5
5
|
activesupport (~> 6.1)
|
|
6
6
|
psych (~> 4.0.1)
|
|
7
7
|
rest-client (~> 2.1)
|
|
@@ -82,7 +82,7 @@ GEM
|
|
|
82
82
|
smart_properties (1.16.3)
|
|
83
83
|
sorbet (0.5.9152)
|
|
84
84
|
sorbet-static (= 0.5.9152)
|
|
85
|
-
sorbet-runtime (0.5.
|
|
85
|
+
sorbet-runtime (0.5.9189)
|
|
86
86
|
sorbet-static (0.5.9152-universal-darwin-20)
|
|
87
87
|
sorbet-static (0.5.9152-x86_64-linux)
|
|
88
88
|
tilt (2.0.10)
|
data/bin/console
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
require "bundler/setup"
|
|
4
4
|
require "mangadex"
|
|
5
5
|
|
|
6
|
-
username, password = [
|
|
6
|
+
username, password, email = [
|
|
7
7
|
ENV['MD_USERNAME'],
|
|
8
8
|
ENV['MD_PASSWORD'],
|
|
9
|
+
ENV['MD_EMAIL'],
|
|
9
10
|
]
|
|
10
11
|
|
|
11
|
-
if username && password
|
|
12
|
-
Mangadex::Auth.login(username, password)
|
|
12
|
+
if (username || email) && password
|
|
13
|
+
Mangadex::Auth.login(username: username, email: email, password: password)
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
# You can add fixtures and/or initialization code here to make experimenting
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# 🔒 Authenticating with Mangadex
|
|
2
|
+
|
|
3
|
+
## Beforehand
|
|
4
|
+
|
|
5
|
+
Any actions that can be performed on the mangadex site as a non authenticated user will not require a user to be logged
|
|
6
|
+
in. Authentication on Mangadex, as per version
|
|
7
|
+
<a href="https://rubygems.org/gems/mangadex"><img src="https://badgen.net/rubygems/v/mangadex" /></a>
|
|
8
|
+
will need an `Authorization` HTTP header to be present.
|
|
9
|
+
|
|
10
|
+
You can check details on the Mangadex API here: https://api.mangadex.org/docs.html#section/Authentication
|
|
11
|
+
|
|
12
|
+
## Authentication & Authorization flow
|
|
13
|
+
|
|
14
|
+
The authentication flow happens as such:
|
|
15
|
+
|
|
16
|
+
1. You login with your email or username, and password.
|
|
17
|
+
2. Upon successfully _authenticating_ your account, you will be given a `session` and a `refresh` tokens.
|
|
18
|
+
3. You must use the `session` token to _authorize_ your account to perform certain actions (ie: create resources, etc.)
|
|
19
|
+
4. You must use the `refresh` token to refresh the `session` when expired.
|
|
20
|
+
|
|
21
|
+
> - The `session` token expires **15 minutes** after been granted.
|
|
22
|
+
> - The `refresh` token refreshes **1 month** after been granted.
|
|
23
|
+
|
|
24
|
+
## Authentication using `mangadex` gem
|
|
25
|
+
|
|
26
|
+
Now that the basics of authentication have been covered, let's go over how it's done on with the gem.
|
|
27
|
+
|
|
28
|
+
### Logging in
|
|
29
|
+
|
|
30
|
+
It's simple to login, whether with your email address or your email address:
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
# With your username
|
|
34
|
+
Mangadex::Auth.login(username: username, password: password)
|
|
35
|
+
|
|
36
|
+
# With your email address
|
|
37
|
+
Mangadex::Auth.login(email: email, password: password)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Upon successful authentication, an instance of `Mangadex::Api::User` will be returned:
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
user = Mangadex::Auth.login(...)
|
|
44
|
+
|
|
45
|
+
# The session token, valid for 15 minutes (String).
|
|
46
|
+
user.session
|
|
47
|
+
|
|
48
|
+
# The refresh token, valid for 1 month (String)
|
|
49
|
+
user.refresh
|
|
50
|
+
|
|
51
|
+
# The logged in user's ID (String) (formatted as a UUID)
|
|
52
|
+
user.mangadex_user_id
|
|
53
|
+
|
|
54
|
+
# Time at the which user.session becomes invalid (Time)
|
|
55
|
+
user.session_valid_until
|
|
56
|
+
|
|
57
|
+
# Miscellaneaous data. When logging in, it's an instance of Mangadex::User
|
|
58
|
+
# (response from the server)
|
|
59
|
+
user.data
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
# Refreshes the tokens now (Boolean)
|
|
64
|
+
user.refresh!
|
|
65
|
+
|
|
66
|
+
# Refreshes the tokens if expired, then return user itself (Mangadex::Api::User)
|
|
67
|
+
user.with_valid_session
|
|
68
|
+
|
|
69
|
+
# Returns if user.session has expired (Boolean)
|
|
70
|
+
user.session_expired?
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
If there's an error, `Mangadex::Errors::AuthenticationError` will be raised. Here's how to handle that scenario:
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
def login(email, password)
|
|
77
|
+
Mangadex::Auth.login(email: email, password: password)
|
|
78
|
+
rescue Mangadex::Errors::AuthenticationError => error
|
|
79
|
+
response = error.response
|
|
80
|
+
|
|
81
|
+
# A list of detailed errors from Mangadex. (Array of
|
|
82
|
+
# Mangadex::Api::Response::Error)
|
|
83
|
+
response.errors.each do |error|
|
|
84
|
+
puts error.id
|
|
85
|
+
puts error.status
|
|
86
|
+
puts error.title
|
|
87
|
+
puts error.detail
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Authenticating requests
|
|
93
|
+
|
|
94
|
+
When the user is logged in, all subsequent requests _should_ be authenticated. Here's an example to retrieve a list of manga that the logged in user is _reading_ at the moment:
|
|
95
|
+
|
|
96
|
+
```ruby
|
|
97
|
+
user = Mangadex::Auth.login(...)
|
|
98
|
+
response = Mangadex::Manga.all_reading_status('reading')
|
|
99
|
+
manga_ids = response['statuses'].keys
|
|
100
|
+
|
|
101
|
+
reading_now = Mangadex::Manga.list(ids: manga_ids)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
If for whatever reason you want to a request not to be authenticated, you can do something like:
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
Mangadex.context.without_user do
|
|
108
|
+
# your mangadex request(s) here
|
|
109
|
+
end
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
When logging in, the user's session information will be persisted in the storage. See below [for more details]().
|
|
113
|
+
|
|
114
|
+
### Logging out
|
|
115
|
+
|
|
116
|
+
Logging the user out is very easy:
|
|
117
|
+
|
|
118
|
+
```ruby
|
|
119
|
+
Mangadex::Auth.logout
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Here, the `user`'s session will be revoked on Mangadex. It will try to delete the user's session. `Mangadex::Auth.logout` outside of the `with_user` block will not do anything.
|
|
123
|
+
|
|
124
|
+
This action also clears the context's user and the storage info associated to this user.
|
|
125
|
+
|
|
126
|
+
## Persisting the user session: storage stragegies
|
|
127
|
+
|
|
128
|
+
### What is this?
|
|
129
|
+
|
|
130
|
+
Using this gem should help you a little bit managing tokens. By default, the gem stores the following information in memory:
|
|
131
|
+
|
|
132
|
+
- For a particular user ID:
|
|
133
|
+
- User session
|
|
134
|
+
- User refresh token
|
|
135
|
+
- User session expiry date
|
|
136
|
+
|
|
137
|
+
### Why is this a thing?
|
|
138
|
+
|
|
139
|
+
Good question. We want to make session management with this gem as easy as possible. The session is used to retrieve a valid logged in user. Here's how it works:
|
|
140
|
+
|
|
141
|
+
- When the user logs in, the refresh token, the session token (as well as it's expired date) are stored for that user
|
|
142
|
+
- When requesting the tokens for the user, a `Mangadex::Api::User` is created with refreshed tokens (if expired).
|
|
143
|
+
- When logging out, if implemented by you, the users's session details are deleted.
|
|
144
|
+
|
|
145
|
+
Here's you retrieve a user from your storage at any point:
|
|
146
|
+
|
|
147
|
+
```ruby
|
|
148
|
+
mangadex_user_id = '...'
|
|
149
|
+
Mangadex::Api::User.from_storage(mangadex_user_id)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
It's up to you to decide how you store the user ID. You don't need to worry about saving the storage, the gem takes care of that for you.
|
|
153
|
+
|
|
154
|
+
### Ok, ok. How can I use my own strategy?
|
|
155
|
+
|
|
156
|
+
By default, this gem ships with `Mangagex::Storage::Memory` which corresponds to the in-memory storage. This should be fine if you don't care much about persisting the user session at any point.
|
|
157
|
+
|
|
158
|
+
No assumptions can be made on which storage service you use. That is 100% up to you how the information is stored. Let's say you want to use [redis](https://github.com/redis/redis) for session instead of the default memory storage stragery:
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
require 'redis'
|
|
162
|
+
|
|
163
|
+
class BasicRedisStragery < Mangadex::Storage::Basic
|
|
164
|
+
# Must be implemented
|
|
165
|
+
def get(mangadex_user_id, key)
|
|
166
|
+
client.hget(mangadex_user_id, key)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Must be implemented
|
|
170
|
+
def set(mangadex_user_id, key, value)
|
|
171
|
+
client.hset(mangadex_user_id, key, value)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Optional - It's a nice-to-have, especially for logging out.
|
|
175
|
+
def clear(mangadex_user_id)
|
|
176
|
+
client.del(mangadex_user_id)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
private
|
|
180
|
+
|
|
181
|
+
def client
|
|
182
|
+
@client ||= Redis.new(url: 'redis://localhost')
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Let the gem know which strategy needs to be used
|
|
187
|
+
Mangadex.configuration.storage_class = BasicRedisStragery
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
> On Rails, you can put this inside an initializer. Example: `config/initializers/mangadex.rb`.
|
|
191
|
+
|
|
192
|
+
The snippet of code is an example of how a storage strategy is implemented. It's important to make sure that neither `get` nor `set` raise exceptions.
|
|
193
|
+
|
|
194
|
+
> - We recommend using redis if you're developing a web app or a bot where authentication is involed.
|
|
195
|
+
> - You can even use a the filesystem if you're building a CLI (command line interface).
|
|
196
|
+
> - We **do not** recommend using SQL at the moment. This might be hard on your app's performance...
|
|
197
|
+
|
|
198
|
+
### Can I opt-out?
|
|
199
|
+
|
|
200
|
+
Of course. Set `Mangadex::Storage::None` as the prefered strategy:
|
|
201
|
+
|
|
202
|
+
```ruby
|
|
203
|
+
# Either
|
|
204
|
+
Mangadex.configure do |config|
|
|
205
|
+
config.storage_class = Mangadex::Storage::None
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Or
|
|
209
|
+
Mangadex.configuration.storage_class = Mangadex::Storage::None
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## About content ratings
|
|
213
|
+
|
|
214
|
+
Each manga/chapter has a content rating (`safe`, `suggestive`, `erotica` and `pornographic`). It might be worth filtering certain titles depending on the audiance. By default, Mangadex filters out every `pornographic` entry.
|
|
215
|
+
|
|
216
|
+
Please note that content rating is not tied to the user at the moment on Mangadex. So it was decided **not** to add this responsiblity on this gem. Instead, the content ratings can be specified on context gem as well, like this:
|
|
217
|
+
|
|
218
|
+
```ruby
|
|
219
|
+
# Everything but "suggestive" content - this is an example :p
|
|
220
|
+
mangas = Mangadex::Api::Content.allow_content_rating('safe', 'erotica', 'pornographic') do
|
|
221
|
+
response = Mangadex::Manga.list
|
|
222
|
+
response.data
|
|
223
|
+
end
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
The advantage of this approach is that you don't have to set the `content_rating` param yourself everywhere.
|
data/docs/context.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Mangadex contexts
|
|
2
|
+
|
|
3
|
+
There is a concept of concepts in this gem. This is there for you to access certain variables at any point in your app.
|
|
4
|
+
|
|
5
|
+
## User
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
Mangadex.context.user # => #<Mangadex::Api::User ...>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This is set to `nil` before logging in.
|
|
12
|
+
|
|
13
|
+
When logging in, the user is stored in the context so that subsequent requests are set to be authenticated with this user.
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
Mangadex::Auth.login(...)
|
|
17
|
+
Mangadex.context.user.nil? # => false
|
|
18
|
+
|
|
19
|
+
custom_lists = Mangadex::CustomList.list
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
If you're not logged in, `Mangadex::Errors::UnauthorizedError` will be raised for any request that requires you to be logged in and authorized to perform a certain account.
|
|
23
|
+
|
|
24
|
+
You can set the user in a temporary context:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
Mangadex.context.user # => nil
|
|
28
|
+
|
|
29
|
+
temp_user = Mangadex::Api::User.new(mangadex_user_id: 'blabla')
|
|
30
|
+
Mangadex.context.with_user(temp_user) do
|
|
31
|
+
Mangadex.context.user # => #<Mangadex::Api::User mangadex_user_id="blabla">
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
Mangadex.context.user # => nil
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
More info on authentication [here]().
|
|
38
|
+
|
|
39
|
+
## Content rating
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
Mangadex.context.allowed_content_ratings # => [#<Mangadex::ContentRating ...>, ...]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Content ratings are not tied to the user. When set, requests that accept a [`content_rating`](https://api.mangadex.org/docs.html#section/Static-data/Manga-content-rating) parameter, this parameter will be set to `Mangadex.context.allowed_content_ratings` if nothing is specified.
|
|
46
|
+
|
|
47
|
+
By default, `safe`, `suggestive` and `erotica` are used on Mangadex. But however, if you want to allow all content ratings, you could do something like:
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
Mangadex.context.allow_content_ratings('safe', 'suggestive', 'erotica', 'pornographic')
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then, a query to fetch manga will make the following request:
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
Mangadex::Manga.list
|
|
57
|
+
# GET https://api.mangadex.org/manga?contentRating%5B%5D=safe&contentRating%5B%5D=suggestive&contentRating%5B%5D=erotica&contentRating%5B%5D=pornographic
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
You can also use temporary content ratings:
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
# old content ratings
|
|
64
|
+
Mangadex.context.allow_content_ratings('safe', 'suggestive', 'erotica', 'pornographic') do
|
|
65
|
+
# temporary content ratings
|
|
66
|
+
Mangadex::Manga.list
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# back to old content ratings
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Tags
|
|
73
|
+
|
|
74
|
+
Get the list of possible tags on Mangadex:
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
Mangadex.context.tags
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### API version
|
|
81
|
+
|
|
82
|
+
Get the current Mangadex's latest API version
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
Mangadex.context.version
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
A warning message will be printed if there's a mismatch between Mangadex's API version and the gem version. Example:
|
|
89
|
+
|
|
90
|
+
| Mangadex's API version | The gem's version | Result |
|
|
91
|
+
| ---------------------- | ----------------- | ------- |
|
|
92
|
+
| 5.3.3 | 5.3.3.1 | OK |
|
|
93
|
+
| 5.3.4 | 5.3.3.4 | Warning |
|
data/lib/config.rb
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
|
|
3
|
+
module Mangadex
|
|
4
|
+
class Config
|
|
5
|
+
extend T::Sig
|
|
6
|
+
|
|
7
|
+
# Class used to persist users
|
|
8
|
+
# Must respond to: :session, :refresh, :mangadex_user_id
|
|
9
|
+
sig { returns(Class) }
|
|
10
|
+
attr_accessor :user_class
|
|
11
|
+
|
|
12
|
+
# Persisting strategy. See Mangadex::Storage::Base for more details.
|
|
13
|
+
sig { returns(Class) }
|
|
14
|
+
attr_accessor :storage_class
|
|
15
|
+
|
|
16
|
+
sig { returns(T::Array[ContentRating]) }
|
|
17
|
+
attr_accessor :default_content_ratings
|
|
18
|
+
|
|
19
|
+
sig { void }
|
|
20
|
+
def initialize
|
|
21
|
+
@user_class = Api::User
|
|
22
|
+
@storage_class = Storage::Memory
|
|
23
|
+
@default_content_ratings = ContentRating.parse(['safe', 'suggestive', 'erotica'])
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
sig { params(klass: Class).void }
|
|
27
|
+
def user_class=(klass)
|
|
28
|
+
missing_methods = [:session, :refresh, :mangadex_user_id] - klass.instance_methods
|
|
29
|
+
if missing_methods.empty?
|
|
30
|
+
@user_class = klass
|
|
31
|
+
else
|
|
32
|
+
raise ArgumentError, 'user_class must respond to :session, :refresh, :mangadex_user_id'
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
sig { params(content_ratings: T::Array[T.any(String, ContentRating)]).void }
|
|
37
|
+
def default_content_ratings=(content_ratings)
|
|
38
|
+
@default_content_ratings = ContentRating.parse(content_ratings)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def storage_class=(klass)
|
|
42
|
+
@storage = nil
|
|
43
|
+
@storage_class = klass
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def storage
|
|
47
|
+
@storage ||= storage_class.new
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/errors.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
|
|
3
|
+
module Mangadex
|
|
4
|
+
module Errors
|
|
5
|
+
# Standard error class for this gem.
|
|
6
|
+
#
|
|
7
|
+
# @author thedrummeraki
|
|
8
|
+
# @since 0.6.0
|
|
9
|
+
class StandardError < ::StandardError
|
|
10
|
+
extend T::Sig
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class UserNotLoggedIn < StandardError
|
|
14
|
+
sig { returns(String) }
|
|
15
|
+
def message
|
|
16
|
+
"You are not logged in. Use [Mangadex::Auth.login] to log in."
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class AuthenticationError < StandardError
|
|
21
|
+
sig { returns(Mangadex::Api::Response) }
|
|
22
|
+
attr_accessor :response
|
|
23
|
+
|
|
24
|
+
sig { params(response: Mangadex::Api::Response).void }
|
|
25
|
+
def initialize(response)
|
|
26
|
+
@response = response
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
sig { returns(String) }
|
|
30
|
+
def message
|
|
31
|
+
"Your username or password may not be correct."
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class UnauthorizedError < AuthenticationError
|
|
36
|
+
sig { returns(String) }
|
|
37
|
+
def message
|
|
38
|
+
"Oops, you are not authorized to make this call. Make sure you log in with the right account."
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
data/lib/mangadex/README.md
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
This is documentation for the `Mangadex` module.
|
|
4
4
|
|
|
5
5
|
### Directory
|
|
6
|
+
|
|
6
7
|
#### Sub-modules
|
|
7
8
|
|
|
8
9
|
- [`Mangadex::Api`](#)
|
|
9
10
|
- [`Mangadex::Internal`](#)
|
|
10
11
|
|
|
11
12
|
#### Fetchable/Resources
|
|
13
|
+
|
|
12
14
|
- [`Mangadex::Artist`](#)
|
|
13
15
|
- [`Mangadex::Auth`](#mangadexauth)
|
|
14
16
|
- [`Mangadex::Author`](#)
|
|
@@ -25,6 +27,7 @@ This is documentation for the `Mangadex` module.
|
|
|
25
27
|
- [`Mangadex::User`](#)
|
|
26
28
|
|
|
27
29
|
#### Other classes
|
|
30
|
+
|
|
28
31
|
- [`Mangadex::MangadexObject`](#)
|
|
29
32
|
- [`Mangadex::Types`](#)
|
|
30
33
|
- [`Mangadex::Version`](#)
|
|
@@ -51,7 +54,7 @@ Mangadex::Auth.login(username, password)
|
|
|
51
54
|
```
|
|
52
55
|
|
|
53
56
|
Login with your username and password. Upon successful login, the user will be available in a context from
|
|
54
|
-
`Mangadex
|
|
57
|
+
`Mangadex.context.user`. This variable can be used anywhere in your application. More info [here](#).
|
|
55
58
|
|
|
56
59
|
> - Returns `Mangadex::Api::Response` if request fails.
|
|
57
60
|
> - Returns `true` if user is logged in.
|
|
@@ -86,8 +89,9 @@ Mangadex::Auth.refresh_token
|
|
|
86
89
|
```
|
|
87
90
|
|
|
88
91
|
Manually cause a token refresh.
|
|
92
|
+
|
|
89
93
|
> Please note that simply calling `Mangadex::Api::Content.user` ensures that the token is valid. More info [here](#).
|
|
90
94
|
|
|
91
95
|
> - Returns `nil` if user is not logged (ie: `Mangadex::Api::Content.user` is `nil`)
|
|
92
96
|
> - Returns `true` if the refresh is successful
|
|
93
|
-
> - Returns `false` if the refresh is [not successful](#).
|
|
97
|
+
> - Returns `false` if the refresh is [not successful](#).
|
|
@@ -7,6 +7,7 @@ module Mangadex
|
|
|
7
7
|
|
|
8
8
|
attr_accessor :result, :response, :errors, :data
|
|
9
9
|
attr_accessor :limit, :offset, :total
|
|
10
|
+
attr_accessor :raw_data
|
|
10
11
|
|
|
11
12
|
def self.attributes_to_inspect
|
|
12
13
|
%i(result errors limit offset total data)
|
|
@@ -40,8 +41,15 @@ module Mangadex
|
|
|
40
41
|
end
|
|
41
42
|
end
|
|
42
43
|
|
|
43
|
-
def errored?
|
|
44
|
-
Array(errors).any?
|
|
44
|
+
def errored?(status=nil)
|
|
45
|
+
errored = Array(errors).any?
|
|
46
|
+
return errored if status.nil?
|
|
47
|
+
|
|
48
|
+
errors.select { |error| error.status.to_s == status.to_s }.any?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def as_json(*)
|
|
52
|
+
Hash(raw_data)
|
|
45
53
|
end
|
|
46
54
|
|
|
47
55
|
private
|
|
@@ -60,6 +68,7 @@ module Mangadex
|
|
|
60
68
|
)
|
|
61
69
|
end
|
|
62
70
|
),
|
|
71
|
+
raw_data: data,
|
|
63
72
|
)
|
|
64
73
|
end
|
|
65
74
|
|
|
@@ -75,6 +84,7 @@ module Mangadex
|
|
|
75
84
|
result: data['result'],
|
|
76
85
|
response: data['response'],
|
|
77
86
|
data: klass.from_data(data['data'] || data),
|
|
87
|
+
raw_data: data,
|
|
78
88
|
)
|
|
79
89
|
end
|
|
80
90
|
|
|
@@ -97,6 +107,7 @@ module Mangadex
|
|
|
97
107
|
end
|
|
98
108
|
)
|
|
99
109
|
),
|
|
110
|
+
raw_data: data,
|
|
100
111
|
)
|
|
101
112
|
end
|
|
102
113
|
end
|
data/lib/mangadex/api/user.rb
CHANGED
|
@@ -7,13 +7,13 @@ module Mangadex
|
|
|
7
7
|
attr_accessor :mangadex_user_id, :session, :refresh, :session_valid_until
|
|
8
8
|
attr_reader :data
|
|
9
9
|
|
|
10
|
-
sig { params(mangadex_user_id: String, session: T.nilable(String), refresh: T.nilable(String), data: T.untyped).void }
|
|
11
|
-
def initialize(mangadex_user_id
|
|
10
|
+
sig { params(mangadex_user_id: String, session: T.nilable(String), refresh: T.nilable(String), data: T.untyped, session_valid_until: T.nilable(Time)).void }
|
|
11
|
+
def initialize(mangadex_user_id:, session: nil, refresh: nil, data: nil, session_valid_until: nil)
|
|
12
12
|
raise ArgumentError, 'Missing mangadex_user_id' if mangadex_user_id.to_s.empty?
|
|
13
13
|
|
|
14
14
|
@mangadex_user_id = mangadex_user_id
|
|
15
15
|
@session = session
|
|
16
|
-
@session_valid_until = session ? Time.now + (14 * 60) : nil
|
|
16
|
+
@session_valid_until = session_valid_until ? session_valid_until : (session ? Time.now + (14 * 60) : nil)
|
|
17
17
|
@refresh = refresh
|
|
18
18
|
@data = data
|
|
19
19
|
end
|
|
@@ -24,9 +24,7 @@ module Mangadex
|
|
|
24
24
|
def refresh!
|
|
25
25
|
return false if refresh.nil?
|
|
26
26
|
|
|
27
|
-
response = Mangadex::
|
|
28
|
-
Mangadex::Internal::Request.post('/auth/refresh', payload: { token: refresh })
|
|
29
|
-
end
|
|
27
|
+
response = Mangadex::Internal::Request.post('/auth/refresh', payload: { token: refresh })
|
|
30
28
|
return false unless response['token']
|
|
31
29
|
|
|
32
30
|
@session_valid_until = Time.now + (14 * 60)
|
|
@@ -36,7 +34,7 @@ module Mangadex
|
|
|
36
34
|
true
|
|
37
35
|
end
|
|
38
36
|
|
|
39
|
-
sig { returns(
|
|
37
|
+
sig { returns(User) }
|
|
40
38
|
def with_valid_session
|
|
41
39
|
session_expired? && refresh!
|
|
42
40
|
self
|
|
@@ -48,6 +46,52 @@ module Mangadex
|
|
|
48
46
|
def session_expired?
|
|
49
47
|
@session_valid_until.nil? || @session_valid_until <= Time.now
|
|
50
48
|
end
|
|
49
|
+
|
|
50
|
+
sig { returns(T::Boolean) }
|
|
51
|
+
def persist
|
|
52
|
+
return false unless valid?
|
|
53
|
+
|
|
54
|
+
Mangadex.storage.set(mangadex_user_id, 'session', session) if session
|
|
55
|
+
Mangadex.storage.set(mangadex_user_id, 'refresh', refresh) if refresh
|
|
56
|
+
if session_valid_until
|
|
57
|
+
Mangadex.storage.set(mangadex_user_id, 'session_valid_until', session_valid_until.to_s)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
sig { returns(T::Boolean) }
|
|
64
|
+
def valid?
|
|
65
|
+
!mangadex_user_id.nil? && !mangadex_user_id.strip.empty?
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
sig { params(mangadex_user_id: T.nilable(String)).returns(T.nilable(User)) }
|
|
69
|
+
def self.from_storage(mangadex_user_id)
|
|
70
|
+
return if mangadex_user_id.nil?
|
|
71
|
+
|
|
72
|
+
session = Mangadex.storage.get(mangadex_user_id, 'session')
|
|
73
|
+
refresh = Mangadex.storage.get(mangadex_user_id, 'refresh')
|
|
74
|
+
session_valid_until = Mangadex.storage.get(mangadex_user_id, 'session_valid_until')
|
|
75
|
+
|
|
76
|
+
user = if session || refresh || session_valid_until
|
|
77
|
+
session_valid_until = session_valid_until ? Time.parse(session_valid_until) : nil
|
|
78
|
+
|
|
79
|
+
new(
|
|
80
|
+
mangadex_user_id: mangadex_user_id,
|
|
81
|
+
session: session,
|
|
82
|
+
refresh: refresh,
|
|
83
|
+
session_valid_until: session_valid_until,
|
|
84
|
+
).with_valid_session
|
|
85
|
+
else
|
|
86
|
+
nil
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
if user
|
|
90
|
+
Mangadex.context.user = user
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
user
|
|
94
|
+
end
|
|
51
95
|
end
|
|
52
96
|
end
|
|
53
97
|
end
|
data/lib/mangadex/api.rb
CHANGED
data/lib/mangadex/artist.rb
CHANGED
|
@@ -2,10 +2,29 @@
|
|
|
2
2
|
require_relative "author"
|
|
3
3
|
|
|
4
4
|
module Mangadex
|
|
5
|
-
class Artist <
|
|
5
|
+
class Artist < MangadexObject
|
|
6
6
|
# Indicates if this is an artist
|
|
7
7
|
#
|
|
8
8
|
# @return [Boolean] whether this is an artist or not.
|
|
9
|
+
has_attributes \
|
|
10
|
+
:name,
|
|
11
|
+
:image_url,
|
|
12
|
+
:biography,
|
|
13
|
+
:twitter,
|
|
14
|
+
:pixiv,
|
|
15
|
+
:melon_book,
|
|
16
|
+
:fan_box,
|
|
17
|
+
:booth,
|
|
18
|
+
:nico_video,
|
|
19
|
+
:skeb,
|
|
20
|
+
:fantia,
|
|
21
|
+
:tumblr,
|
|
22
|
+
:youtube,
|
|
23
|
+
:website,
|
|
24
|
+
:version,
|
|
25
|
+
:created_at,
|
|
26
|
+
:updated_at
|
|
27
|
+
|
|
9
28
|
def artist?
|
|
10
29
|
true
|
|
11
30
|
end
|