mangadex 5.3.3.1 → 5.3.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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 +5 -2
- data/lib/mangadex/api/user.rb +51 -7
- data/lib/mangadex/api.rb +0 -1
- data/lib/mangadex/auth.rb +42 -13
- data/lib/mangadex/internal/context.rb +141 -0
- data/lib/mangadex/internal/request.rb +8 -6
- data/lib/mangadex/internal.rb +1 -0
- data/lib/mangadex/manga.rb +5 -3
- 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/user.rb +2 -2
- data/lib/mangadex/version.rb +1 -1
- data/lib/mangadex.rb +25 -12
- metadata +11 -3
- data/lib/mangadex/api/context.rb +0 -137
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d01b0fac553138d7ac86d1313737d86ba5415ee88e2ca6de08787402be7e3fb
|
4
|
+
data.tar.gz: 643923fe081fb046f6feec8ab4ce945a358a2fc9d66681d732a272b9bad2223d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a196f878697f4c7f1a65178cee78a6d36b1c23c9466d0b997ee3ece51bbc0497db0fc0a3f6f16361a1d7c7518733afe7357bbc2a5cb785deaabe07d45df1aec5
|
7
|
+
data.tar.gz: b657aa48b952ae4b3136bc52c6e5f96f7d3287ae26d08089a0aaf294313a9662d1dfa2ca35477702b4269ad42af53f2b97e7e9eee575142b0c27b295c789de78
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
mangadex (5.3.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](#).
|
@@ -41,8 +41,11 @@ module Mangadex
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
def errored?
|
45
|
-
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?
|
46
49
|
end
|
47
50
|
|
48
51
|
def as_json(*)
|
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/auth.rb
CHANGED
@@ -3,16 +3,20 @@ module Mangadex
|
|
3
3
|
class Auth
|
4
4
|
extend T::Sig
|
5
5
|
|
6
|
-
sig { params(username: String, password: String).returns(T.
|
7
|
-
def self.login(username, password)
|
6
|
+
sig { params(username: T.nilable(String), email: T.nilable(String), password: String).returns(T.nilable(Mangadex::Api::User)) }
|
7
|
+
def self.login(username: nil, email: nil, password: nil)
|
8
|
+
args = { password: password }
|
9
|
+
args.merge!(email: email) if email
|
10
|
+
args.merge!(username: username) if username
|
11
|
+
|
8
12
|
response = Mangadex::Internal::Request.post(
|
9
13
|
'/auth/login',
|
10
|
-
payload: {
|
11
|
-
username:
|
12
|
-
|
13
|
-
|
14
|
+
payload: Mangadex::Internal::Definition.validate(args, {
|
15
|
+
username: { accepts: String },
|
16
|
+
email: { accepts: String },
|
17
|
+
password: { accepts: String, required: true },
|
18
|
+
}),
|
14
19
|
)
|
15
|
-
return response if response.is_a?(Mangadex::Api::Response) && response.errored?
|
16
20
|
|
17
21
|
session = response.dig('token', 'session')
|
18
22
|
refresh = response.dig('token', 'refresh')
|
@@ -20,13 +24,19 @@ module Mangadex
|
|
20
24
|
mangadex_user = Mangadex::Internal::Request.get('/user/me', headers: { Authorization: session })
|
21
25
|
|
22
26
|
user = Mangadex::Api::User.new(
|
23
|
-
mangadex_user.data.id,
|
27
|
+
mangadex_user_id: mangadex_user.data.id,
|
24
28
|
session: session,
|
25
29
|
refresh: refresh,
|
26
30
|
data: mangadex_user.data,
|
27
31
|
)
|
28
|
-
|
29
|
-
|
32
|
+
return if user.session_expired?
|
33
|
+
|
34
|
+
Mangadex.context.user = user
|
35
|
+
|
36
|
+
user.persist
|
37
|
+
user
|
38
|
+
rescue Errors::UnauthorizedError => error
|
39
|
+
raise Errors::AuthenticationError.new(error.response)
|
30
40
|
end
|
31
41
|
|
32
42
|
sig { returns(Hash) }
|
@@ -41,20 +51,39 @@ module Mangadex
|
|
41
51
|
|
42
52
|
sig { returns(T.any(T::Boolean, Mangadex::Api::Response)) }
|
43
53
|
def self.logout
|
44
|
-
return true if Mangadex
|
54
|
+
return true if Mangadex.context.user.nil?
|
45
55
|
|
46
56
|
response = Mangadex::Internal::Request.post(
|
47
57
|
'/auth/logout',
|
48
58
|
)
|
49
59
|
return reponse if response.is_a?(Mangadex::Api::Response) && response.errored?
|
50
60
|
|
51
|
-
|
61
|
+
clear_user
|
62
|
+
true
|
63
|
+
rescue Mangadex::Errors::UnauthorizedError
|
64
|
+
clear_user
|
52
65
|
true
|
53
66
|
end
|
54
67
|
|
55
68
|
sig { returns(T::Boolean) }
|
56
69
|
def self.refresh_token
|
57
|
-
!(Mangadex
|
70
|
+
!(Mangadex.context.user&.refresh!).nil?
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
sig { void }
|
76
|
+
def self.clear_user
|
77
|
+
return if Mangadex.context.user.nil?
|
78
|
+
|
79
|
+
if Mangadex.context.user.respond_to?(:session=)
|
80
|
+
Mangadex.context.user.session = nil
|
81
|
+
end
|
82
|
+
if Mangadex.context.user.respond_to?(:refresh=)
|
83
|
+
Mangadex.context.user.refresh = nil
|
84
|
+
end
|
85
|
+
Mangadex.storage.clear(Mangadex.context.user.mangadex_user_id)
|
86
|
+
Mangadex.context.user = nil
|
58
87
|
end
|
59
88
|
end
|
60
89
|
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# typed: true
|
2
|
+
module Mangadex
|
3
|
+
module Internal
|
4
|
+
class Context
|
5
|
+
extend T::Sig
|
6
|
+
|
7
|
+
sig { returns(T::Array[Mangadex::ContentRating]) }
|
8
|
+
attr_accessor :allowed_content_ratings, :ignore_user
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@allowed_content_ratings = Mangadex.configuration.default_content_ratings
|
12
|
+
end
|
13
|
+
|
14
|
+
sig { returns(T.nilable(String)) }
|
15
|
+
def version
|
16
|
+
@version ||= Mangadex::Api::VersionChecker.check_mangadex_version
|
17
|
+
end
|
18
|
+
|
19
|
+
sig { returns(T.nilable(Mangadex::Api::User)) }
|
20
|
+
def user
|
21
|
+
@ignore_user ? nil : @user&.with_valid_session
|
22
|
+
rescue Mangadex::Errors::UnauthorizedError
|
23
|
+
warn("A user is present but not authenticated!")
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
sig { returns(T::Array[Mangadex::Tag]) }
|
28
|
+
def tags
|
29
|
+
@tags ||= Mangadex::Tag.list.data
|
30
|
+
end
|
31
|
+
|
32
|
+
sig { params(user: T.nilable(T.any(Hash, Mangadex::Api::User, Mangadex::User)), block: T.proc.returns(T.untyped)).returns(T.untyped) }
|
33
|
+
def with_user(user, &block)
|
34
|
+
temp_set_value("user", user) do
|
35
|
+
yield
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
sig { params(block: T.proc.returns(T.untyped)).returns(T.untyped) }
|
40
|
+
def without_user(&block)
|
41
|
+
temp_set_value("ignore_user", true) do
|
42
|
+
yield
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
sig { params(user: T.nilable(T.untyped)).void }
|
47
|
+
def user=(user)
|
48
|
+
if user.is_a?(Mangadex::Api::User)
|
49
|
+
@user = user
|
50
|
+
elsif user.is_a?(Mangadex::User)
|
51
|
+
@user = Mangadex::Api::User.new(
|
52
|
+
mangadex_user_id: user.id,
|
53
|
+
data: user,
|
54
|
+
)
|
55
|
+
elsif user.is_a?(Hash)
|
56
|
+
user = Mangadex::Internal::Definition.validate(user, {
|
57
|
+
mangadex_user_id: { accepts: String, required: true },
|
58
|
+
session: { accepts: String },
|
59
|
+
refresh: { accepts: String },
|
60
|
+
})
|
61
|
+
|
62
|
+
@user = Mangadex::Api::User.new(
|
63
|
+
mangadex_user_id: user[:mangadex_user_id],
|
64
|
+
session: user[:session],
|
65
|
+
refresh: user[:refresh],
|
66
|
+
)
|
67
|
+
elsif user_object?(user)
|
68
|
+
@user = Mangadex::Api::User.new(
|
69
|
+
mangadex_user_id: user.mangadex_user_id.to_s,
|
70
|
+
session: user.session,
|
71
|
+
refresh: user.refresh,
|
72
|
+
data: user,
|
73
|
+
)
|
74
|
+
elsif user.nil?
|
75
|
+
@user = nil
|
76
|
+
else
|
77
|
+
raise TypeError, "Invalid user type."
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def allow_content_ratings(*content_ratings, &block)
|
82
|
+
content_ratings = Mangadex::ContentRating.parse(Array(content_ratings))
|
83
|
+
if block_given?
|
84
|
+
content_ratings = Mangadex.context.allowed_content_ratings if content_ratings.empty?
|
85
|
+
|
86
|
+
# set temporarily
|
87
|
+
temp_set_value("allowed_content_ratings", content_ratings) do
|
88
|
+
yield
|
89
|
+
end
|
90
|
+
elsif content_ratings.any?
|
91
|
+
# set "permanently"
|
92
|
+
@allowed_content_ratings = content_ratings
|
93
|
+
else
|
94
|
+
# This is to throw an exception prompting to pass a block if there no params.
|
95
|
+
yield
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def with_allowed_content_ratings(*other_content_ratings, &block)
|
100
|
+
T.unsafe(self).allow_content_ratings(*(allowed_content_ratings + other_content_ratings)) do
|
101
|
+
yield
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Only recommended for development and debugging only
|
106
|
+
def force_raw_requests(&block)
|
107
|
+
if block_given?
|
108
|
+
temp_set_value("force_raw_requests", true) do
|
109
|
+
yield
|
110
|
+
end
|
111
|
+
else
|
112
|
+
!!@force_raw_requests
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def user_object?(user)
|
119
|
+
return false if user.nil?
|
120
|
+
|
121
|
+
missing_methods = [:session, :refresh, :mangadex_user_id] - user.methods
|
122
|
+
return true if missing_methods.empty?
|
123
|
+
|
124
|
+
warn("Potential user object #{user} is missing #{missing_methods}")
|
125
|
+
false
|
126
|
+
end
|
127
|
+
|
128
|
+
def temp_set_value(name, value, &block)
|
129
|
+
setter_method_name = "#{name}="
|
130
|
+
|
131
|
+
current_value = send(name)
|
132
|
+
send(setter_method_name, value)
|
133
|
+
response = yield
|
134
|
+
send(setter_method_name, current_value)
|
135
|
+
response
|
136
|
+
ensure
|
137
|
+
send(setter_method_name, current_value) if current_value
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -54,7 +54,7 @@ module Mangadex
|
|
54
54
|
payload_details = request_payload ? "Payload: #{request_payload}" : "{no-payload}"
|
55
55
|
puts("[#{self.class.name}] #{method.to_s.upcase} #{request_url} #{payload_details}")
|
56
56
|
|
57
|
-
raise Mangadex::UserNotLoggedIn.new if auth && Mangadex
|
57
|
+
raise Mangadex::Errors::UserNotLoggedIn.new if auth && Mangadex.context.user.nil?
|
58
58
|
|
59
59
|
start_time = Time.now
|
60
60
|
|
@@ -63,11 +63,13 @@ module Mangadex
|
|
63
63
|
elapsed_time = ((end_time - start_time) * 1000).to_i
|
64
64
|
puts("[#{self.class.name}] took #{elapsed_time} ms")
|
65
65
|
|
66
|
-
raw_request = raw || Mangadex
|
66
|
+
raw_request = raw || Mangadex.context.force_raw_requests
|
67
67
|
|
68
68
|
if (body = @response.body)
|
69
69
|
raw_request ? try_json(body) : Mangadex::Api::Response.coerce(try_json(body))
|
70
70
|
end
|
71
|
+
rescue RestClient::Unauthorized => error
|
72
|
+
raise Errors::UnauthorizedError.new(Mangadex::Api::Response.coerce(try_json(error.response.body)))
|
71
73
|
rescue RestClient::Exception => error
|
72
74
|
if (body = error.response.body)
|
73
75
|
raw_request ? try_json(body) : Mangadex::Api::Response.coerce(JSON.parse(body)) rescue raise error
|
@@ -90,8 +92,8 @@ module Mangadex
|
|
90
92
|
|
91
93
|
def self.with_content_rating(data)
|
92
94
|
content_rating = data.has_key?(:content_rating) ? data[:content_rating] : []
|
93
|
-
Mangadex
|
94
|
-
data[:content_rating] = Mangadex
|
95
|
+
Mangadex.context.allow_content_ratings(*content_rating) do
|
96
|
+
data[:content_rating] = Mangadex.context.allowed_content_ratings
|
95
97
|
end
|
96
98
|
data
|
97
99
|
end
|
@@ -108,10 +110,10 @@ module Mangadex
|
|
108
110
|
end
|
109
111
|
|
110
112
|
def request_headers
|
111
|
-
return headers if Mangadex
|
113
|
+
return headers if Mangadex.context.user.nil?
|
112
114
|
|
113
115
|
headers.merge({
|
114
|
-
Authorization: Mangadex
|
116
|
+
Authorization: Mangadex.context.user.with_valid_session.session,
|
115
117
|
})
|
116
118
|
end
|
117
119
|
|
data/lib/mangadex/internal.rb
CHANGED
data/lib/mangadex/manga.rb
CHANGED
@@ -123,14 +123,16 @@ module Mangadex
|
|
123
123
|
)
|
124
124
|
end
|
125
125
|
|
126
|
-
sig { params(
|
127
|
-
def self.all_reading_status(
|
126
|
+
sig { params(status: String).returns(T::Api::GenericResponse) }
|
127
|
+
def self.all_reading_status(status)
|
128
|
+
args = { status: status }
|
129
|
+
|
128
130
|
Mangadex::Internal::Request.get(
|
129
131
|
'/manga/status',
|
130
132
|
Mangadex::Internal::Definition.validate(args, {
|
131
133
|
status: {
|
132
134
|
accepts: %w(reading on_hold dropped plan_to_read re_reading completed),
|
133
|
-
converts:
|
135
|
+
converts: :to_s,
|
134
136
|
},
|
135
137
|
})
|
136
138
|
)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Mangadex
|
2
|
+
module Storage
|
3
|
+
class Basic
|
4
|
+
def get(_scope, _key)
|
5
|
+
raise NotImplementedError
|
6
|
+
end
|
7
|
+
|
8
|
+
def set(_scope, _key, _value)
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
def clear(_scope)
|
13
|
+
warn("Don't know how to clear #{self.class} storage strategy! Skipping...")
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Mangadex
|
2
|
+
module Storage
|
3
|
+
class Memory < BasicObject
|
4
|
+
def initialize
|
5
|
+
@storage = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def get(scope, key)
|
9
|
+
@storage.dig(scope.to_s, key.to_s)
|
10
|
+
end
|
11
|
+
|
12
|
+
def set(scope, key, value)
|
13
|
+
key = key.to_s
|
14
|
+
@storage[scope] = {} unless @storage.has_key?(scope)
|
15
|
+
@storage[scope][key] = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def clear(scope)
|
19
|
+
@storage.delete(scope)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/mangadex/user.rb
CHANGED
@@ -60,7 +60,7 @@ module Mangadex
|
|
60
60
|
def self.follows_user(id)
|
61
61
|
Mangadex::Internal::Definition.must(id)
|
62
62
|
|
63
|
-
return if Mangadex
|
63
|
+
return if Mangadex.context.user.nil?
|
64
64
|
|
65
65
|
data = Mangadex::Internal::Request.get(
|
66
66
|
'/user/follows/user/%{id}' % {id: id},
|
@@ -90,7 +90,7 @@ module Mangadex
|
|
90
90
|
def self.follows_manga(id)
|
91
91
|
Mangadex::Internal::Definition.must(id)
|
92
92
|
|
93
|
-
return if Mangadex
|
93
|
+
return if Mangadex.context.user.nil?
|
94
94
|
|
95
95
|
data = Mangadex::Internal::Request.get(
|
96
96
|
'/user/follows/manga/%{id}' % {id: id},
|
data/lib/mangadex/version.rb
CHANGED
data/lib/mangadex.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: true
|
2
2
|
require 'sorbet-runtime'
|
3
3
|
|
4
4
|
require 'active_support'
|
@@ -14,22 +14,35 @@ require "mangadex/types"
|
|
14
14
|
# API, to interact with Mangadex
|
15
15
|
require "mangadex/api"
|
16
16
|
|
17
|
+
# Persist strategies
|
18
|
+
require "mangadex/storage"
|
19
|
+
|
20
|
+
require_relative "config"
|
21
|
+
require_relative "errors"
|
22
|
+
|
17
23
|
# Namespace for classes and modules for this gem.
|
18
24
|
# @since 5.3.0
|
19
25
|
|
20
26
|
module Mangadex
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
class << self
|
28
|
+
def configuration
|
29
|
+
@configuration ||= Config.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def context
|
33
|
+
@context ||= Internal::Context.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def configure(&block)
|
37
|
+
yield(configuration)
|
38
|
+
end
|
39
|
+
|
40
|
+
def storage
|
41
|
+
configuration.storage
|
42
|
+
end
|
28
43
|
|
29
|
-
|
30
|
-
|
31
|
-
def message
|
32
|
-
"You are not logged in. Use [Mangadex::Auth.login] to log in."
|
44
|
+
def api_version
|
45
|
+
context.version
|
33
46
|
end
|
34
47
|
end
|
35
48
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mangadex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.3.3.
|
4
|
+
version: 5.3.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Akinyele Cafe-Febrissy
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09
|
11
|
+
date: 2021-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: psych
|
@@ -170,11 +170,14 @@ files:
|
|
170
170
|
- Rakefile
|
171
171
|
- bin/console
|
172
172
|
- bin/setup
|
173
|
+
- docs/authentication.md
|
174
|
+
- docs/context.md
|
175
|
+
- lib/config.rb
|
176
|
+
- lib/errors.rb
|
173
177
|
- lib/extensions.rb
|
174
178
|
- lib/mangadex.rb
|
175
179
|
- lib/mangadex/README.md
|
176
180
|
- lib/mangadex/api.rb
|
177
|
-
- lib/mangadex/api/context.rb
|
178
181
|
- lib/mangadex/api/response.rb
|
179
182
|
- lib/mangadex/api/user.rb
|
180
183
|
- lib/mangadex/api/version_checker.rb
|
@@ -186,6 +189,7 @@ files:
|
|
186
189
|
- lib/mangadex/cover_art.rb
|
187
190
|
- lib/mangadex/custom_list.rb
|
188
191
|
- lib/mangadex/internal.rb
|
192
|
+
- lib/mangadex/internal/context.rb
|
189
193
|
- lib/mangadex/internal/definition.rb
|
190
194
|
- lib/mangadex/internal/request.rb
|
191
195
|
- lib/mangadex/internal/with_attributes.rb
|
@@ -195,6 +199,10 @@ files:
|
|
195
199
|
- lib/mangadex/report_reason.rb
|
196
200
|
- lib/mangadex/scanlation_group.rb
|
197
201
|
- lib/mangadex/sorbet.rb
|
202
|
+
- lib/mangadex/storage.rb
|
203
|
+
- lib/mangadex/storage/basic.rb
|
204
|
+
- lib/mangadex/storage/memory.rb
|
205
|
+
- lib/mangadex/storage/none.rb
|
198
206
|
- lib/mangadex/tag.rb
|
199
207
|
- lib/mangadex/types.rb
|
200
208
|
- lib/mangadex/upload.rb
|
data/lib/mangadex/api/context.rb
DELETED
@@ -1,137 +0,0 @@
|
|
1
|
-
# typed: true
|
2
|
-
module Mangadex
|
3
|
-
module Api
|
4
|
-
class Context
|
5
|
-
extend T::Sig
|
6
|
-
|
7
|
-
DEFAULT_MANGADEX_CONTENT_RATING_VALUES = [
|
8
|
-
ContentRating::SAFE,
|
9
|
-
ContentRating::SUGGESTIVE,
|
10
|
-
ContentRating::EROTICA,
|
11
|
-
].freeze
|
12
|
-
|
13
|
-
@@user = nil
|
14
|
-
@@version = nil
|
15
|
-
@@force_raw_requests = nil
|
16
|
-
@@tags = nil
|
17
|
-
@@allowed_content_ratings = DEFAULT_MANGADEX_CONTENT_RATING_VALUES
|
18
|
-
|
19
|
-
sig { returns(T.nilable(String)) }
|
20
|
-
def self.version
|
21
|
-
return @@version unless @@version.nil?
|
22
|
-
|
23
|
-
@@version = Mangadex::Api::VersionChecker.check_mangadex_version
|
24
|
-
end
|
25
|
-
|
26
|
-
sig { returns(T.nilable(Mangadex::Api::User)) }
|
27
|
-
def self.user
|
28
|
-
@@user&.with_valid_session
|
29
|
-
end
|
30
|
-
|
31
|
-
sig { returns(T::Array[Mangadex::Tag]) }
|
32
|
-
def self.tags
|
33
|
-
return @@tags if @@tags
|
34
|
-
|
35
|
-
@@tags = Mangadex::Tag.list.data
|
36
|
-
end
|
37
|
-
|
38
|
-
sig { returns(T::Array[Mangadex::ContentRating]) }
|
39
|
-
def self.allowed_content_ratings
|
40
|
-
@@allowed_content_ratings.map { |value| ContentRating.new(value) }
|
41
|
-
end
|
42
|
-
|
43
|
-
sig { params(user: T.nilable(T.any(Hash, Mangadex::Api::User, Mangadex::User))).void }
|
44
|
-
def self.user=(user)
|
45
|
-
if user.is_a?(Mangadex::Api::User)
|
46
|
-
@@user = user
|
47
|
-
elsif user.is_a?(Mangadex::User)
|
48
|
-
@@user = Mangadex::Api::User.new(
|
49
|
-
user.id,
|
50
|
-
data: user,
|
51
|
-
)
|
52
|
-
elsif user.is_a?(Hash)
|
53
|
-
user = Mangadex::Internal::Definition.validate(user, {
|
54
|
-
mangadex_user_id: { accepts: String, required: true },
|
55
|
-
session: { accepts: String },
|
56
|
-
refresh: { accepts: String },
|
57
|
-
})
|
58
|
-
|
59
|
-
@@user = Mangadex::Api::User.new(
|
60
|
-
user[:mangadex_user_id],
|
61
|
-
session: user[:session],
|
62
|
-
refresh: user[:refresh],
|
63
|
-
)
|
64
|
-
elsif user.nil?
|
65
|
-
@@user = nil
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
sig { params(user: T.nilable(T.any(Hash, Mangadex::Api::User, Mangadex::User)), block: T.proc.returns(T.untyped)).returns(T.untyped) }
|
70
|
-
def self.with_user(user, &block)
|
71
|
-
temp_set_value("user", user) do
|
72
|
-
yield
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
sig { params(block: T.proc.returns(T.untyped)).returns(T.untyped) }
|
77
|
-
def self.without_user(&block)
|
78
|
-
with_user(nil) do
|
79
|
-
yield
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def self.force_raw_requests(&block)
|
84
|
-
if block_given?
|
85
|
-
temp_set_value("force_raw_requests", true) do
|
86
|
-
yield
|
87
|
-
end
|
88
|
-
else
|
89
|
-
!!@@force_raw_requests
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def self.force_raw_requests=(value)
|
94
|
-
@@force_raw_requests = value
|
95
|
-
end
|
96
|
-
|
97
|
-
def self.allow_content_ratings(*content_ratings, &block)
|
98
|
-
content_ratings = if content_ratings.empty?
|
99
|
-
allowed_content_ratings
|
100
|
-
else
|
101
|
-
Mangadex::ContentRating.parse(content_ratings)
|
102
|
-
end
|
103
|
-
if block_given?
|
104
|
-
# set temporarily
|
105
|
-
temp_set_value("allowed_content_ratings", content_ratings) do
|
106
|
-
yield
|
107
|
-
end
|
108
|
-
elsif content_ratings.any?
|
109
|
-
# set "permanently"
|
110
|
-
@@allowed_content_ratings = content_ratings
|
111
|
-
else
|
112
|
-
# This is to throw an exception prompting to pass a block if there no params.
|
113
|
-
yield
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def self.with_allowed_content_ratings(*other_content_ratings, &block)
|
118
|
-
T.unsafe(self).allow_content_ratings(*(allowed_content_ratings + other_content_ratings)) do
|
119
|
-
yield
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
private
|
124
|
-
|
125
|
-
def self.temp_set_value(name, value, &block)
|
126
|
-
var_name = "@@#{name}"
|
127
|
-
current_value = class_variable_get(var_name)
|
128
|
-
class_variable_set(var_name, value)
|
129
|
-
response = yield
|
130
|
-
class_variable_set(var_name, current_value)
|
131
|
-
response
|
132
|
-
ensure
|
133
|
-
class_variable_set(var_name, current_value) if current_value
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|