mangadex 5.3.1.1 → 5.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c3906abcda03214729faefa84f1f28cf7685a56bb31d2759a75728c2dfe8633
4
- data.tar.gz: 8ad9182042f2e00bd2d796d1278fbdd6ba3413ef66cd8c2c9946d2e79f5c9dc4
3
+ metadata.gz: 166fb230b0125992e5168515129718a28f7d545c3c1cb07f9bc81e837ad8c2c7
4
+ data.tar.gz: cf310df080bb7fdce3df2fd885aa478de4ae050272e58d97ce6fdbe0b60459af
5
5
  SHA512:
6
- metadata.gz: d5e8f6bb17f8b565fd5b9068089282370c5f6b88d2707331ceeabbd35a7372f937c9a8e71ee41fe6c32b249950ed8908a429456d65369610ee1976b50329122a
7
- data.tar.gz: d4e78fc2cae3bdc612b2cf739d989a5590e2a95fe6256dfc2cc5c9120dd07a727d2557dc9ae9461b16e080c0bb8950e8562333679c0cef7f569e4c6d5c917b9e
6
+ metadata.gz: 4babccf80e64908e70f612d5afb152b00fef108c827cbfc75a273478ee2f1230b6b2366318bab5a3fadb3b2025e0e7a64bed88746c04484d18a9c1a62a241e2a
7
+ data.tar.gz: aebcdeed93c99b1beb9e4723e8371875c21da6629311270cbf2b6ca5c58c55b0dca39e8a222bcd886180ee7b1059e40853948f90a25553da4dea8f1d261b4f44
@@ -0,0 +1,36 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [culture]
13
+ pull_request:
14
+ branches: [culture]
15
+
16
+ jobs:
17
+ test:
18
+ runs-on: ubuntu-latest
19
+ strategy:
20
+ matrix:
21
+ ruby-version: ["2.7", "3.0"]
22
+
23
+ steps:
24
+ - uses: actions/checkout@v2
25
+ - name: Set up Ruby
26
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
27
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
28
+ # uses: ruby/setup-ruby@v1
29
+ uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
30
+ with:
31
+ ruby-version: ${{ matrix.ruby-version }}
32
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
33
+ - name: Run tests
34
+ run: bundle exec rspec
35
+ - name: Run sorbet typecheck
36
+ run: bundle exec srb tc
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mangadex (5.3.1)
4
+ mangadex (5.3.2)
5
5
  activesupport (~> 6.1)
6
6
  psych (~> 4.0.1)
7
7
  rest-client (~> 2.1)
@@ -16,11 +16,16 @@ GEM
16
16
  minitest (>= 5.1)
17
17
  tzinfo (~> 2.0)
18
18
  zeitwerk (~> 2.3)
19
+ addressable (2.8.0)
20
+ public_suffix (>= 2.0.2, < 5.0)
19
21
  coderay (1.1.3)
20
22
  concurrent-ruby (1.1.9)
23
+ crack (0.4.5)
24
+ rexml
21
25
  diff-lcs (1.4.4)
22
26
  domain_name (0.5.20190701)
23
27
  unf (>= 0.0.5, < 1.0.0)
28
+ hashdiff (1.0.1)
24
29
  http-accept (1.7.0)
25
30
  http-cookie (1.0.4)
26
31
  domain_name (~> 0.5)
@@ -31,17 +36,30 @@ GEM
31
36
  mime-types-data (~> 3.2015)
32
37
  mime-types-data (3.2021.0901)
33
38
  minitest (5.14.4)
39
+ mustermann (1.1.1)
40
+ ruby2_keywords (~> 0.0.1)
34
41
  netrc (0.11.0)
35
42
  pry (0.14.1)
36
43
  coderay (~> 1.1)
37
44
  method_source (~> 1.0)
38
45
  psych (4.0.1)
39
- rake (10.5.0)
46
+ public_suffix (4.0.6)
47
+ rack (2.2.3)
48
+ rack-protection (2.1.0)
49
+ rack
50
+ rake (13.0.6)
51
+ request_interceptor (1.0.0)
52
+ activesupport (>= 4.0)
53
+ rack
54
+ sinatra
55
+ smart_properties (~> 1.0)
56
+ webmock (~> 3.0)
40
57
  rest-client (2.1.0)
41
58
  http-accept (>= 1.7.0, < 2.0)
42
59
  http-cookie (>= 1.0.2, < 2.0)
43
60
  mime-types (>= 1.16, < 4.0)
44
61
  netrc (~> 0.8)
62
+ rexml (3.2.5)
45
63
  rspec (3.10.0)
46
64
  rspec-core (~> 3.10.0)
47
65
  rspec-expectations (~> 3.10.0)
@@ -55,16 +73,28 @@ GEM
55
73
  diff-lcs (>= 1.2.0, < 2.0)
56
74
  rspec-support (~> 3.10.0)
57
75
  rspec-support (3.10.2)
76
+ ruby2_keywords (0.0.5)
77
+ sinatra (2.1.0)
78
+ mustermann (~> 1.0)
79
+ rack (~> 2.2)
80
+ rack-protection (= 2.1.0)
81
+ tilt (~> 2.0)
82
+ smart_properties (1.16.3)
58
83
  sorbet (0.5.9152)
59
84
  sorbet-static (= 0.5.9152)
60
- sorbet-runtime (0.5.9152)
85
+ sorbet-runtime (0.5.9161)
61
86
  sorbet-static (0.5.9152-universal-darwin-20)
62
87
  sorbet-static (0.5.9152-x86_64-linux)
88
+ tilt (2.0.10)
63
89
  tzinfo (2.0.4)
64
90
  concurrent-ruby (~> 1.0)
65
91
  unf (0.1.4)
66
92
  unf_ext
67
93
  unf_ext (0.0.8)
94
+ webmock (3.14.0)
95
+ addressable (>= 2.8.0)
96
+ crack (>= 0.3.2)
97
+ hashdiff (>= 0.4.0, < 2.0.0)
68
98
  zeitwerk (2.4.2)
69
99
 
70
100
  PLATFORMS
@@ -75,7 +105,8 @@ DEPENDENCIES
75
105
  bundler (~> 2.2.19)
76
106
  mangadex!
77
107
  pry
78
- rake (~> 10.0)
108
+ rake (~> 13.0)
109
+ request_interceptor (~> 1.0.0)
79
110
  rspec (~> 3.0)
80
111
  sorbet
81
112
 
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Ruby](https://github.com/thedrummeraki/mangadex/actions/workflows/ruby.yml/badge.svg)](https://github.com/thedrummeraki/mangadex/actions/workflows/ruby.yml)<a href="https://rubygems.org/gems/mangadex"><img src="https://badgen.net/rubygems/v/mangadex" /></a>
2
+
1
3
  # Mangadex
2
4
 
3
5
  Welcome to `mangadex`, your next favourite Ruby gem for interacting with [Mangadex](https://mangadex.org).
@@ -20,7 +22,7 @@ Or install it yourself as:
20
22
 
21
23
  ## Usage
22
24
 
23
- Please note that I tried my best to follow Mangadex's naming conventions for [their documentation](https://api.mangadex.org).
25
+ Please note that I tried my best to follow Mangadex's naming conventions for [their documentation](https://api.mangadex.org). Track the progress [here in an issue](https://github.com/thedrummeraki/mangadex/issues/5).
24
26
  To find out how to use the gem, you're welcome to [check this out](lib/mangadex).
25
27
 
26
28
  ## Development
@@ -2,52 +2,89 @@
2
2
  module Mangadex
3
3
  module Api
4
4
  class Context
5
+ extend T::Sig
6
+
5
7
  @@user = nil
8
+ @@version = nil
9
+ @@force_raw_requests = nil
6
10
 
7
- class << self
8
- def user
9
- @@user&.with_valid_session
10
- end
11
+ sig { returns(T.nilable(String)) }
12
+ def self.version
13
+ return @@version unless @@version.nil?
11
14
 
12
- def user=(user)
13
- if user.is_a?(Mangadex::Api::User)
14
- @@user = user
15
- elsif user.is_a?(Mangadex::User)
16
- @@user = Mangadex::Api::User.new(
17
- user.id,
18
- data: user,
19
- )
20
- elsif user.is_a?(Hash)
21
- user = user.with_indifferent_access
22
-
23
- @@user = Mangadex::Api::User.new(
24
- user[:mangadex_user_id],
25
- session: user[:session],
26
- refresh: user[:refresh],
27
- )
28
- elsif user.nil?
29
- @@user = nil
30
- else
31
- raise ArgumentError, "Must be an instance of #{Mangadex::Api::User}, #{Mangadex::User} or Hash"
32
- end
33
- end
15
+ @@version = Mangadex::Api::Version.check_mangadex_version
16
+ end
34
17
 
35
- def with_user(user)
36
- current_user = @@user
18
+ sig { returns(T.nilable(Mangadex::Api::User)) }
19
+ def self.user
20
+ @@user&.with_valid_session
21
+ end
22
+
23
+ sig { params(user: T.nilable(T.any(Hash, Mangadex::Api::User, Mangadex::User))).void }
24
+ def self.user=(user)
25
+ if user.is_a?(Mangadex::Api::User)
37
26
  @@user = user
38
- response = yield
39
- @@user = current_user
40
- response
41
- ensure
42
- @@user = current_user
27
+ elsif user.is_a?(Mangadex::User)
28
+ @@user = Mangadex::Api::User.new(
29
+ user.id,
30
+ data: user,
31
+ )
32
+ elsif user.is_a?(Hash)
33
+ user = user.with_indifferent_access
34
+
35
+ @@user = Mangadex::Api::User.new(
36
+ user[:mangadex_user_id],
37
+ session: user[:session],
38
+ refresh: user[:refresh],
39
+ )
40
+ elsif user.nil?
41
+ @@user = nil
43
42
  end
43
+ end
44
44
 
45
- def without_user
46
- with_user(nil) do
45
+ sig { params(user: T.nilable(T.any(Hash, Mangadex::Api::User, Mangadex::User)), block: T.proc.returns(T.untyped)).returns(T.untyped) }
46
+ def self.with_user(user, &block)
47
+ current_user = @@user
48
+ @@user = user
49
+ response = yield
50
+ @@user = current_user
51
+ response
52
+ ensure
53
+ @@user = current_user
54
+ end
55
+
56
+ sig { params(block: T.proc.returns(T.untyped)).returns(T.untyped) }
57
+ def self.without_user(&block)
58
+ with_user(nil) do
59
+ yield
60
+ end
61
+ end
62
+
63
+ def self.force_raw_requests(&block)
64
+ if block_given?
65
+ temp_force_raw_requests do
47
66
  yield
48
67
  end
68
+ else
69
+ !!@@force_raw_requests
49
70
  end
50
71
  end
72
+
73
+ def self.force_raw_requests=(value)
74
+ @@force_raw_requests = value
75
+ end
76
+
77
+ private
78
+
79
+ def self.temp_force_raw_requests(&block)
80
+ current_force_raw_requests = @@force_raw_requests
81
+ @@force_raw_requests = true
82
+ response = yield
83
+ @@force_raw_requests = current_force_raw_requests
84
+ response
85
+ ensure
86
+ @@force_raw_requests = current_force_raw_requests
87
+ end
51
88
  end
52
89
  end
53
90
  end
@@ -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,6 +41,14 @@ module Mangadex
40
41
  end
41
42
  end
42
43
 
44
+ def errored?
45
+ Array(errors).any?
46
+ end
47
+
48
+ def as_json(*)
49
+ Hash(raw_data)
50
+ end
51
+
43
52
  private
44
53
 
45
54
  def self.coerce_errors(data)
@@ -56,6 +65,7 @@ module Mangadex
56
65
  )
57
66
  end
58
67
  ),
68
+ raw_data: data,
59
69
  )
60
70
  end
61
71
 
@@ -71,6 +81,7 @@ module Mangadex
71
81
  result: data['result'],
72
82
  response: data['response'],
73
83
  data: klass.from_data(data['data'] || data),
84
+ raw_data: data,
74
85
  )
75
86
  end
76
87
 
@@ -93,12 +104,9 @@ module Mangadex
93
104
  end
94
105
  )
95
106
  ),
107
+ raw_data: data,
96
108
  )
97
109
  end
98
-
99
- def errored?
100
- Array(errors).any?
101
- end
102
110
  end
103
111
  end
104
112
  end
@@ -2,9 +2,12 @@
2
2
  module Mangadex
3
3
  module Api
4
4
  class User
5
+ extend T::Sig
6
+
5
7
  attr_accessor :mangadex_user_id, :session, :refresh, :session_valid_until
6
8
  attr_reader :data
7
9
 
10
+ sig { params(mangadex_user_id: String, session: T.nilable(String), refresh: T.nilable(String), data: T.untyped).void }
8
11
  def initialize(mangadex_user_id, session: nil, refresh: nil, data: nil)
9
12
  raise ArgumentError, 'Missing mangadex_user_id' if mangadex_user_id.to_s.empty?
10
13
 
@@ -15,9 +18,9 @@ module Mangadex
15
18
  @data = data
16
19
  end
17
20
 
18
- # nil: Nothing happened, no need to refresh the token
19
21
  # true: The tokens were successfully refreshed
20
22
  # false: Error: refresh token empty or could not refresh the token on the server
23
+ sig { returns(T::Boolean) }
21
24
  def refresh!
22
25
  return false if refresh.nil?
23
26
 
@@ -33,6 +36,7 @@ module Mangadex
33
36
  true
34
37
  end
35
38
 
39
+ sig { returns(Mangadex::Api::User) }
36
40
  def with_valid_session
37
41
  session_expired? && refresh!
38
42
  self
@@ -40,6 +44,7 @@ module Mangadex
40
44
  self
41
45
  end
42
46
 
47
+ sig { returns(T::Boolean) }
43
48
  def session_expired?
44
49
  @session_valid_until.nil? || @session_valid_until <= Time.now
45
50
  end
@@ -0,0 +1,31 @@
1
+ # typed: true
2
+ require "psych"
3
+
4
+ module Mangadex
5
+ module Api
6
+ class Version
7
+ extend T::Sig
8
+
9
+ sig { returns(T.nilable(String)) }
10
+ def self.check_mangadex_version
11
+ puts("Checking Mangadex's latest API version...")
12
+ version = Psych.load(
13
+ RestClient.get(
14
+ 'https://api.mangadex.org/api.yaml',
15
+ ).body,
16
+ ).dig('info', 'version')
17
+
18
+ if version != Mangadex::Version::STRING
19
+ warn(
20
+ "[Warning] This gem is compatible with #{Mangadex::Version::STRING} but it looks like Mangadex is at #{version}",
21
+ "[Warning] Check out #{Mangadex::Internal::Request::BASE_URI} for more information.",
22
+ )
23
+ end
24
+
25
+ version
26
+ rescue => error
27
+ nil
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/mangadex/api.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # typed: strict
2
- require_relative "api/version"
2
+ require_relative "api/version_checker"
3
3
  require_relative "api/context"
4
4
  require_relative "api/response"
5
5
  require_relative "api/user"
data/lib/mangadex/auth.rb CHANGED
@@ -1,56 +1,60 @@
1
1
  # typed: false
2
2
  module Mangadex
3
3
  class Auth
4
- class << self
5
- def login(username, password)
6
- response = Mangadex::Internal::Request.post(
7
- '/auth/login',
8
- payload: {
9
- username: username,
10
- password: password,
11
- },
12
- )
13
- return response if response.is_a?(Mangadex::Api::Response) && response.errored?
14
-
15
- session = response.dig('token', 'session')
16
- refresh = response.dig('token', 'refresh')
17
-
18
- mangadex_user = Mangadex::Internal::Request.get('/user/me', headers: { Authorization: session })
4
+ extend T::Sig
5
+
6
+ sig { params(username: String, password: String).returns(T.any(T::Boolean, Mangadex::Api::Response)) }
7
+ def self.login(username, password)
8
+ response = Mangadex::Internal::Request.post(
9
+ '/auth/login',
10
+ payload: {
11
+ username: username,
12
+ password: password,
13
+ },
14
+ )
15
+ return response if response.is_a?(Mangadex::Api::Response) && response.errored?
16
+
17
+ session = response.dig('token', 'session')
18
+ refresh = response.dig('token', 'refresh')
19
+
20
+ mangadex_user = Mangadex::Internal::Request.get('/user/me', headers: { Authorization: session })
21
+
22
+ user = Mangadex::Api::User.new(
23
+ mangadex_user.data.id,
24
+ session: session,
25
+ refresh: refresh,
26
+ data: mangadex_user.data,
27
+ )
28
+ Mangadex::Api::Context.user = user
29
+ !user.session_expired?
30
+ end
19
31
 
20
- user = Mangadex::Api::User.new(
21
- mangadex_user.data.id,
22
- session: session,
23
- refresh: refresh,
24
- data: mangadex_user.data,
32
+ sig { returns(Hash) }
33
+ def self.check_token
34
+ JSON.parse(
35
+ Mangadex::Internal::Request.get(
36
+ '/auth/check',
37
+ raw: true,
25
38
  )
26
- Mangadex::Api::Context.user = user
27
- !user.session_expired?
28
- end
29
-
30
- def check_token
31
- JSON.parse(
32
- Mangadex::Internal::Request.get(
33
- '/auth/check',
34
- raw: true,
35
- )
36
- )
37
- end
39
+ )
40
+ end
38
41
 
39
- def logout
40
- return true if Mangadex::Api::Context.user.nil?
42
+ sig { returns(T.any(T::Boolean, Mangadex::Api::Response)) }
43
+ def self.logout
44
+ return true if Mangadex::Api::Context.user.nil?
41
45
 
42
- response = Mangadex::Internal::Request.post(
43
- '/auth/logout',
44
- )
45
- return reponse if response.is_a?(Mangadex::Api::Response) && response.errored?
46
+ response = Mangadex::Internal::Request.post(
47
+ '/auth/logout',
48
+ )
49
+ return reponse if response.is_a?(Mangadex::Api::Response) && response.errored?
46
50
 
47
- Mangadex::Api::Context.user = nil
48
- true
49
- end
51
+ Mangadex::Api::Context.user = nil
52
+ true
53
+ end
50
54
 
51
- def refresh_token
52
- !(Mangadex::Api::Context.user&.refresh!).nil?
53
- end
55
+ sig { returns(T::Boolean) }
56
+ def self.refresh_token
57
+ !(Mangadex::Api::Context.user&.refresh!).nil?
54
58
  end
55
59
  end
56
60
  end
@@ -4,7 +4,24 @@ require_relative 'mangadex_object'
4
4
 
5
5
  module Mangadex
6
6
  class Author < MangadexObject
7
- has_attributes :name, :image_url, :biography, :version, :created_at, :updated_at
7
+ has_attributes \
8
+ :name,
9
+ :image_url,
10
+ :biography,
11
+ :twitter,
12
+ :pixiv,
13
+ :melon_book,
14
+ :fan_box,
15
+ :booth,
16
+ :nicovideo,
17
+ :skeb,
18
+ :fantia,
19
+ :tumblr,
20
+ :youtube,
21
+ :website,
22
+ :version,
23
+ :created_at,
24
+ :updated_at
8
25
 
9
26
  # List all authors.
10
27
  # Path: +GET /author+
@@ -49,6 +66,8 @@ module Mangadex
49
66
  # @return [Mangadex::Api::Response] with a entity of author
50
67
  sig { params(id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[Author]) }
51
68
  def self.get(id, **args)
69
+ Mangadex::Internal::Definition.must(id)
70
+
52
71
  Mangadex::Internal::Request.get(
53
72
  format('/author/%{id}', id: id),
54
73
  Mangadex::Internal::Definition.validate(args, {
@@ -64,6 +83,8 @@ module Mangadex
64
83
  # @return [Mangadex::Api::Response] with a entity of author
65
84
  sig { params(id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[Author]) }
66
85
  def self.update(id, **args)
86
+ Mangadex::Internal::Definition.must(id)
87
+
67
88
  Mangadex::Internal::Request.put(
68
89
  format('/author/%{id}', id: id),
69
90
  payload: Mangadex::Internal::Definition.validate(args, {
@@ -81,6 +102,8 @@ module Mangadex
81
102
  # @return [Hash]
82
103
  sig { params(id: String).returns(Hash) }
83
104
  def self.delete(id)
105
+ Mangadex::Internal::Definition.must(id)
106
+
84
107
  Mangadex::Internal::Request.delete(
85
108
  format('/author/%{id}', id: id)
86
109
  )
@@ -90,6 +113,10 @@ module Mangadex
90
113
  [:name]
91
114
  end
92
115
 
116
+ class << self
117
+ alias_method :view, :get
118
+ end
119
+
93
120
  # Indicates if this is an artist
94
121
  #
95
122
  # @return [Boolean] whether this is an artist or not.
@@ -31,6 +31,8 @@ module Mangadex
31
31
 
32
32
  sig { params(id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[Chapter]) }
33
33
  def self.get(id, **args)
34
+ Mangadex::Internal::Definition.must(id)
35
+
34
36
  Mangadex::Internal::Request.get(
35
37
  '/chapter/%{id}' % {id: id},
36
38
  Mangadex::Internal::Definition.validate(args, {
@@ -41,6 +43,8 @@ module Mangadex
41
43
 
42
44
  sig { params(id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[Chapter]) }
43
45
  def self.update(id, **args)
46
+ Mangadex::Internal::Definition.must(id)
47
+
44
48
  Mangadex::Internal::Request.put(
45
49
  '/chapter/%{id}' % {id: id},
46
50
  payload: Mangadex::Internal::Definition.validate(args, {
@@ -56,11 +60,17 @@ module Mangadex
56
60
 
57
61
  sig { params(id: String).returns(Hash) }
58
62
  def self.delete(id)
63
+ Mangadex::Internal::Definition.must(id)
64
+
59
65
  Mangadex::Internal::Request.delete(
60
66
  '/chapter/%{id}' % {id: id},
61
67
  )
62
68
  end
63
69
 
70
+ class << self
71
+ alias_method :view, :get
72
+ end
73
+
64
74
  sig { returns(String) }
65
75
  def title
66
76
  attributes&.title.presence || chapter.presence && "Chapter #{chapter}" || "N/A"
@@ -64,7 +64,7 @@ module Mangadex
64
64
 
65
65
  private
66
66
 
67
- sig { params(value: T.any(T::Api::Text, T::Api::ContentRating)).void }
67
+ sig { params(value: T.any(T::Api::Text, T::Api::ContentRating)).returns(T.any(T::Api::Text, T::Api::ContentRating)) }
68
68
  def ensure_value!(value)
69
69
  return value if value.is_a?(ContentRating)
70
70
  return value if VALUES.include?(value)
@@ -47,6 +47,8 @@ module Mangadex
47
47
 
48
48
  sig { params(id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[CoverArt]) }
49
49
  def self.get(id, **args)
50
+ Mangadex::Internal::Definition.must(id)
51
+
50
52
  Mangadex::Internal::Request.get(
51
53
  '/cover/%{id}' % {id: id},
52
54
  Mangadex::Internal::Definition.validate(args, {
@@ -57,6 +59,8 @@ module Mangadex
57
59
 
58
60
  sig { params(id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[CoverArt]) }
59
61
  def self.edit(id, **args)
62
+ Mangadex::Internal::Definition.must(id)
63
+
60
64
  Mangadex::Internal::Request.put(
61
65
  '/cover/%{id}' % {id: id},
62
66
  Mangadex::Internal::Definition.validate(args, {
@@ -69,11 +73,18 @@ module Mangadex
69
73
 
70
74
  sig { params(id: String).returns(Hash) }
71
75
  def self.delete(id)
76
+ Mangadex::Internal::Definition.must(id)
77
+
72
78
  Mangadex::Internal::Request.delete(
73
79
  '/cover/%{id}' % {id: id},
74
80
  )
75
81
  end
76
82
 
83
+ class << self
84
+ alias_method :view, :get
85
+ alias_method :update, :edit
86
+ end
87
+
77
88
  sig { params(size: T::Api::Text).returns(T.nilable(String)) }
78
89
  def image_url(size: :small)
79
90
  return unless manga.present?
@@ -24,6 +24,8 @@ module Mangadex
24
24
 
25
25
  sig { params(id: String).returns(Mangadex::Api::Response[CustomList]) }
26
26
  def self.get(id)
27
+ Mangadex::Internal::Definition.must(id)
28
+
27
29
  Mangadex::Internal::Request.get(
28
30
  '/list/%{id}' % {id: id},
29
31
  )
@@ -31,6 +33,8 @@ module Mangadex
31
33
 
32
34
  sig { params(id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[CustomList]) }
33
35
  def self.update(id, **args)
36
+ Mangadex::Internal::Definition.must(id)
37
+
34
38
  Mangadex::Internal::Request.put(
35
39
  '/list/%{id}' % {id: id},
36
40
  payload: Mangadex::Internal::Definition.validate(args, {
@@ -44,6 +48,8 @@ module Mangadex
44
48
 
45
49
  sig { params(id: String).returns(T::Boolean) }
46
50
  def self.delete(id)
51
+ Mangadex::Internal::Definition.must(id)
52
+
47
53
  Mangadex::Internal::Request.delete(
48
54
  '/list/%{id}' % {id: id},
49
55
  )
@@ -51,6 +57,8 @@ module Mangadex
51
57
 
52
58
  sig { params(id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[Chapter]) }
53
59
  def self.feed(id, **args)
60
+ Mangadex::Internal::Definition.must(id)
61
+
54
62
  Mangadex::Internal::Request.get(
55
63
  '/list/%{id}/feed' % {id: id},
56
64
  Mangadex::Internal::Definition.chapter_list(args),
@@ -59,6 +67,8 @@ module Mangadex
59
67
 
60
68
  sig { params(id: String, list_id: String).returns(T::Boolean) }
61
69
  def self.add_manga(id, list_id:)
70
+ Mangadex::Internal::Definition.must(id)
71
+
62
72
  response = Mangadex::Internal::Request.post(
63
73
  '/manga/%{id}/list/%{list_id}' % {id: id, list_id: list_id},
64
74
  )
@@ -71,6 +81,8 @@ module Mangadex
71
81
 
72
82
  sig { params(id: String, list_id: String).returns(T::Boolean) }
73
83
  def self.remove_manga(id, list_id:)
84
+ Mangadex::Internal::Definition.must(id)
85
+
74
86
  response = Mangadex::Internal::Request.delete(
75
87
  '/manga/%{id}/list/%{list_id}' % {id: id, list_id: list_id},
76
88
  )
@@ -94,6 +106,8 @@ module Mangadex
94
106
 
95
107
  sig { params(user_id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[CustomList]) }
96
108
  def self.user_list(user_id, **args)
109
+ Mangadex::Internal::Definition.must(user_id)
110
+
97
111
  Mangadex::Internal::Request.get(
98
112
  '/user/%{id}/list' % {id: user_id},
99
113
  Mangadex::Internal::Definition.validate(args, {
@@ -103,6 +117,11 @@ module Mangadex
103
117
  )
104
118
  end
105
119
 
120
+ class << self
121
+ alias_method :view, :get
122
+ alias_method :edit, :update
123
+ end
124
+
106
125
  sig { params(id: String).returns(T::Boolean) }
107
126
  def add_manga(id)
108
127
  Mangadex::CustomList.add_manga(id, list_id: self.id)
@@ -120,6 +120,19 @@ module Mangadex
120
120
  )
121
121
  end
122
122
 
123
+ def must(*args)
124
+ args = args.each_with_index.map do |arg, index|
125
+ ["arg_at_position_#{index}".to_sym, arg]
126
+ end.to_h
127
+
128
+ definition = args.keys.map do |key|
129
+ [key, { required: true }]
130
+ end.to_h
131
+
132
+ validate(args, definition)
133
+ args.values
134
+ end
135
+
123
136
  def validate(args, definition)
124
137
  args = Hash(args).with_indifferent_access
125
138
  definition = Hash(definition).with_indifferent_access
@@ -144,7 +157,7 @@ module Mangadex
144
157
  if errors.any?
145
158
  error_message = errors.map do |error|
146
159
  if error[:extra]
147
- "params[:#{error[:extra]}] does not exist and cannot be passed to this request"
160
+ "paalidate_required!rams[:#{error[:extra]}] does not exist and cannot be passed to this request"
148
161
  elsif error[:message]
149
162
  error[:message]
150
163
  else
@@ -62,13 +62,15 @@ module Mangadex
62
62
  end_time = Time.now
63
63
  elapsed_time = ((end_time - start_time) * 1000).to_i
64
64
  puts("[#{self.class.name}] took #{elapsed_time} ms")
65
+
66
+ raw_request = raw || Mangadex::Api::Context.force_raw_requests
65
67
 
66
- if @response.body
67
- raw ? @response.body : Mangadex::Api::Response.coerce(JSON.parse(@response.body))
68
+ if (body = @response.body)
69
+ raw_request ? try_json(body) : Mangadex::Api::Response.coerce(try_json(body))
68
70
  end
69
71
  rescue RestClient::Exception => error
70
- if error.response.body
71
- raw ? error.response.body : Mangadex::Api::Response.coerce(JSON.parse(error.response.body))
72
+ if (body = error.response.body)
73
+ raw_request ? try_json(body) : Mangadex::Api::Response.coerce(JSON.parse(body)) rescue raise error
72
74
  else
73
75
  raise error
74
76
  end
@@ -116,6 +118,12 @@ module Mangadex
116
118
 
117
119
  raise "Invalid method: #{method}. Must be one of: #{ALLOWED_METHODS}"
118
120
  end
121
+
122
+ def try_json(body)
123
+ JSON.parse(body)
124
+ rescue JSON::ParserError
125
+ body
126
+ end
119
127
  end
120
128
  end
121
129
  end
@@ -11,7 +11,8 @@ module Mangadex
11
11
  :id,
12
12
  :type,
13
13
  :attributes,
14
- :relationships
14
+ :relationships,
15
+ :related_type
15
16
 
16
17
  class_methods do
17
18
  USING_ATTRIBUTES = {}
@@ -30,7 +31,7 @@ module Mangadex
30
31
  self.name.split('::').last.underscore
31
32
  end
32
33
 
33
- def from_data(data)
34
+ def from_data(data, related_type: nil)
34
35
  base_class_name = self.name.gsub('::', '_')
35
36
  klass_name = self.name
36
37
  target_attributes_class_name = "#{base_class_name}_Attributes"
@@ -65,6 +66,7 @@ module Mangadex
65
66
  id: data['id'],
66
67
  type: data['type'] || self.type,
67
68
  attributes: attributes,
69
+ related_type: related_type,
68
70
  }
69
71
 
70
72
  initialize_hash.merge!({relationships: relationships}) if relationships.present?
@@ -110,6 +112,13 @@ module Mangadex
110
112
  else
111
113
  super
112
114
  end
115
+ elsif !related_type.nil?
116
+ return super unless method_name.end_with?("?")
117
+
118
+ looking_for_related = method_name.to_s.split("?").first
119
+ return super unless Mangadex::Relationship::RELATED_VALUES.include?(looking_for_related)
120
+
121
+ related_type == looking_for_related
113
122
  else
114
123
  super
115
124
  end
@@ -66,6 +66,8 @@ module Mangadex
66
66
 
67
67
  sig { params(id: String, args: T::Api::Arguments).returns(T::Api::MangaResponse) }
68
68
  def self.view(id, **args)
69
+ Mangadex::Internal::Definition.must(id)
70
+
69
71
  Mangadex::Internal::Request.get(
70
72
  '/manga/%{id}' % {id: id},
71
73
  Mangadex::Internal::Definition.validate(args, {
@@ -76,6 +78,8 @@ module Mangadex
76
78
 
77
79
  sig { params(id: String).returns(T.any(Hash, Mangadex::Api::Response)) }
78
80
  def self.unfollow(id)
81
+ Mangadex::Internal::Definition.must(id)
82
+
79
83
  Mangadex::Internal::Request.delete(
80
84
  '/manga/%{id}/follow' % {id: id},
81
85
  )
@@ -83,6 +87,8 @@ module Mangadex
83
87
 
84
88
  sig { params(id: String).returns(T.any(Hash, Mangadex::Api::Response)) }
85
89
  def self.follow(id)
90
+ Mangadex::Internal::Definition.must(id)
91
+
86
92
  Mangadex::Internal::Request.post(
87
93
  '/manga/%{id}/follow' % {id: id},
88
94
  )
@@ -90,6 +96,8 @@ module Mangadex
90
96
 
91
97
  sig { params(id: String, args: T::Api::Arguments).returns(T::Api::ChapterResponse) }
92
98
  def self.feed(id, **args)
99
+ Mangadex::Internal::Definition.must(id)
100
+
93
101
  Mangadex::Internal::Request.get(
94
102
  '/manga/%{id}/feed' % {id: id},
95
103
  Mangadex::Internal::Definition.chapter_list(args),
@@ -128,6 +136,8 @@ module Mangadex
128
136
 
129
137
  sig { params(id: String).returns(T::Api::GenericResponse) }
130
138
  def self.reading_status(id)
139
+ Mangadex::Internal::Definition.must(id)
140
+
131
141
  Mangadex::Internal::Request.get(
132
142
  '/manga/%{id}/status' % {id: id},
133
143
  )
@@ -135,6 +145,8 @@ module Mangadex
135
145
 
136
146
  sig { params(id: String, status: String).returns(T::Api::GenericResponse) }
137
147
  def self.update_reading_status(id, status)
148
+ Mangadex::Internal::Definition.must(id)
149
+
138
150
  Mangadex::Internal::Request.post(
139
151
  '/manga/%{id}/status' % {id: id},
140
152
  payload: Mangadex::Internal::Definition.validate({status: status}, {
@@ -149,11 +161,15 @@ module Mangadex
149
161
  # Untested API endpoints
150
162
  sig { params(id: String, args: T::Api::Arguments).returns(T::Api::MangaResponse) }
151
163
  def self.update(id, **args)
164
+ Mangadex::Internal::Definition.must(id)
165
+
152
166
  Mangadex::Internal::Request.put('/manga/%{id}' % {id: id}, payload: args)
153
167
  end
154
168
 
155
169
  sig { params(id: String).returns(Hash) }
156
170
  def self.delete(id)
171
+ Mangadex::Internal::Definition.must(id)
172
+
157
173
  Mangadex::Internal::Request.delete(
158
174
  '/manga/%{id}' % {id: id},
159
175
  )
@@ -169,6 +185,8 @@ module Mangadex
169
185
 
170
186
  class << self
171
187
  alias_method :aggregate, :volumes_and_chapters
188
+ alias_method :get, :view
189
+ alias_method :edit, :update
172
190
  end
173
191
 
174
192
  sig { returns(T.nilable(ContentRating)) }
@@ -1,33 +1,45 @@
1
1
  # typed: false
2
2
  module Mangadex
3
3
  class Relationship < MangadexObject
4
- attr_accessor :id, :type, :attributes
4
+ attr_accessor :id, :type, :related, :attributes
5
+
6
+ RELATED_VALUES = %w(
7
+ monochrome
8
+ main_story
9
+ adapted_from
10
+ based_on
11
+ prequel
12
+ side_story
13
+ doujinshi
14
+ same_franchise
15
+ shared_universe
16
+ sequel
17
+ spin_off
18
+ alternate_story
19
+ preserialization
20
+ colored
21
+ serialization
22
+ ).freeze
5
23
 
6
24
  class << self
7
25
  def from_data(data)
8
26
  data = data.with_indifferent_access
9
27
  klass = class_for_relationship_type(data['type'])
10
28
 
11
- return klass.from_data(data) if klass && data['attributes']&.any?
29
+ if klass && data['attributes']&.any?
30
+ return klass.from_data(data, related_type: data['related'])
31
+ end
12
32
 
13
33
  new(
14
34
  id: data['id'],
15
35
  type: data['type'],
16
36
  attributes: OpenStruct.new(data['attributes']),
37
+ related: data['related'],
17
38
  )
18
39
  end
19
40
 
20
41
  private
21
42
 
22
- def build_attributes(data)
23
- klass = class_for_relationship_type(data['type'])
24
- if klass.present?
25
- klass.from_data(data)
26
- else
27
- OpenStruct.new(data['attributes'])
28
- end
29
- end
30
-
31
43
  def class_for_relationship_type(type)
32
44
  module_parts = self.name.split('::')
33
45
  module_name = module_parts.take(module_parts.size - 1).join('::')
@@ -39,8 +51,18 @@ module Mangadex
39
51
  end
40
52
  end
41
53
 
42
- def inspect
43
- "#<#{self.class} id=#{id.inspect} type=#{type.inspect}>"
54
+ def self.attributes_to_inspect
55
+ [:id, :type, :related]
56
+ end
57
+
58
+
59
+ def method_missing(value)
60
+ return super unless value.end_with?("?")
61
+
62
+ looking_for_related = value.to_s.split("?").first
63
+ return super unless RELATED_VALUES.include?(looking_for_related)
64
+
65
+ !related.nil? && related == looking_for_related
44
66
  end
45
67
  end
46
68
  end
@@ -3,6 +3,7 @@ module Mangadex
3
3
  class ScanlationGroup < MangadexObject
4
4
  has_attributes \
5
5
  :name,
6
+ :alt_names,
6
7
  :website,
7
8
  :irc_channel,
8
9
  :irc_server,
@@ -47,6 +48,8 @@ module Mangadex
47
48
  end
48
49
 
49
50
  def view(id)
51
+ Mangadex::Internal::Definition.must(id)
52
+
50
53
  Mangadex::Internal::Request.get(
51
54
  '/group/%{id}' % {id: id},
52
55
  Mangadex::Internal::Definition.validate(args, {
@@ -91,6 +94,11 @@ module Mangadex
91
94
  end
92
95
  end
93
96
 
97
+ class << self
98
+ alias_method :get, :view
99
+ alias_method :edit, :update
100
+ end
101
+
94
102
  def self.inspect_attributes
95
103
  self.attributes - [:version, :created_at, :updated_at]
96
104
  end
@@ -17,7 +17,8 @@ module T
17
17
  MangaResponse = T.type_alias do
18
18
  T.any(
19
19
  Mangadex::Api::Response[Mangadex::Manga],
20
- Mangadex::Api::Response[T::Array[Mangadex::Manga]]
20
+ Mangadex::Api::Response[T::Array[Mangadex::Manga]],
21
+ Hash,
21
22
  )
22
23
  end
23
24
  ChapterResponse = T.type_alias do
@@ -28,6 +28,8 @@ module Mangadex
28
28
  alias_method :begin, :start
29
29
 
30
30
  def upload_images(upload_session_id)
31
+ Mangadex::Internal::Definition.must(upload_session_id)
32
+
31
33
  Mangadex::Internal::Request.post(
32
34
  '/upload/%{upload_session_id}' % {upload_session_id: upload_session_id},
33
35
  payload: Mangadex::Internal::Definition.validate(args, {
@@ -37,6 +39,8 @@ module Mangadex
37
39
  end
38
40
 
39
41
  def abandon(upload_session_id)
42
+ Mangadex::Internal::Definition.must(upload_session_id)
43
+
40
44
  Mangadex::Internal::Request.delete(
41
45
  '/upload/%{upload_session_id}' % {upload_session_id: upload_session_id},
42
46
  )
@@ -44,6 +48,8 @@ module Mangadex
44
48
  alias_method :stop, :abandon
45
49
 
46
50
  def commit(upload_session_id, **args)
51
+ Mangadex::Internal::Definition.must(upload_session_id)
52
+
47
53
  Mangadex::Internal::Request.post(
48
54
  '/upload/%{upload_session_id}/commit' % {upload_session_id: upload_session_id},
49
55
  payload: Mangadex::Internal::Definition.validate(args, {
@@ -54,6 +60,8 @@ module Mangadex
54
60
  end
55
61
 
56
62
  def delete_uploaded_image(upload_session_id, upload_session_file_id)
63
+ Mangadex::Internal::Definition.must(upload_session_id)
64
+
57
65
  Mangadex::Internal::Request.delete(
58
66
  '/upload/%{upload_session_id}/%{upload_session_file_id}' % {
59
67
  upload_session_id: upload_session_id,
@@ -63,6 +71,8 @@ module Mangadex
63
71
  end
64
72
 
65
73
  def delete_uploaded_images(upload_session_id, upload_session_file_ids)
74
+ Mangadex::Internal::Definition.must(upload_session_id)
75
+
66
76
  Mangadex::Internal::Request.delete(
67
77
  '/upload/%{upload_session_id}' % {upload_session_id: upload_session_id},
68
78
  payload: Array(upload_session_file_id),
data/lib/mangadex/user.rb CHANGED
@@ -30,6 +30,8 @@ module Mangadex
30
30
 
31
31
  sig { params(id: String).returns(T::Boolean) }
32
32
  def self.follows_group(id)
33
+ Mangadex::Internal::Definition.must(id)
34
+
33
35
  data = Mangadex::Internal::Request.get(
34
36
  '/user/follows/group/%{id}' % {id: id},
35
37
  raw: true,
@@ -55,6 +57,8 @@ module Mangadex
55
57
 
56
58
  sig { params(id: String).returns(T::Boolean) }
57
59
  def self.follows_user(id)
60
+ Mangadex::Internal::Definition.must(id)
61
+
58
62
  return if Mangadex::Api::Context.user.nil?
59
63
 
60
64
  data = Mangadex::Internal::Request.get(
@@ -83,6 +87,8 @@ module Mangadex
83
87
 
84
88
  sig { params(id: String).returns(T::Boolean) }
85
89
  def self.follows_manga(id)
90
+ Mangadex::Internal::Definition.must(id)
91
+
86
92
  return if Mangadex::Api::Context.user.nil?
87
93
 
88
94
  data = Mangadex::Internal::Request.get(
@@ -1,4 +1,12 @@
1
- # typed: strict
1
+ # typed: false
2
2
  module Mangadex
3
- VERSION = "5.3.1.1"
3
+ module Version
4
+ MAJOR = "5"
5
+ MINOR = "3"
6
+ TINY = "3"
7
+ PATCH = nil
8
+
9
+ STRING = [MAJOR, MINOR, TINY].compact.join('.')
10
+ FULL = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
11
+ end
4
12
  end
data/mangadex.gemspec CHANGED
@@ -5,7 +5,7 @@ require "mangadex/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "mangadex"
8
- spec.version = Mangadex::VERSION
8
+ spec.version = Mangadex::Version::FULL
9
9
  spec.authors = ["Akinyele Cafe-Febrissy"]
10
10
  spec.email = ["me@akinyele.ca"]
11
11
 
@@ -28,8 +28,9 @@ Gem::Specification.new do |spec|
28
28
  spec.add_dependency "sorbet-runtime"
29
29
 
30
30
  spec.add_development_dependency "bundler", "~> 2.2.19"
31
- spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "rake", "~> 13.0"
32
32
  spec.add_development_dependency "rspec", "~> 3.0"
33
+ spec.add_development_dependency "request_interceptor", "~> 1.0.0"
33
34
  spec.add_development_dependency "pry"
34
35
  spec.add_development_dependency "sorbet"
35
36
  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.1.1
4
+ version: 5.3.3
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-22 00:00:00.000000000 Z
11
+ date: 2021-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: psych
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '10.0'
89
+ version: '13.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '10.0'
96
+ version: '13.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rspec
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '3.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: request_interceptor
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.0.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 1.0.0
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: pry
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -143,6 +157,7 @@ executables: []
143
157
  extensions: []
144
158
  extra_rdoc_files: []
145
159
  files:
160
+ - ".github/workflows/ruby.yml"
146
161
  - ".gitignore"
147
162
  - ".rspec"
148
163
  - ".ruby-version"
@@ -162,7 +177,7 @@ files:
162
177
  - lib/mangadex/api/context.rb
163
178
  - lib/mangadex/api/response.rb
164
179
  - lib/mangadex/api/user.rb
165
- - lib/mangadex/api/version.rb
180
+ - lib/mangadex/api/version_checker.rb
166
181
  - lib/mangadex/artist.rb
167
182
  - lib/mangadex/auth.rb
168
183
  - lib/mangadex/author.rb
@@ -1,23 +0,0 @@
1
- # typed: true
2
- require "psych"
3
-
4
- module Mangadex
5
- module Api
6
- VERSION = -> do
7
- version = Psych.load(
8
- RestClient.get(
9
- 'https://api.mangadex.org/api.yaml',
10
- ).body,
11
- ).dig('info', 'version')
12
-
13
- if version != Mangadex::VERSION
14
- warn(
15
- "[Warning] This gem is compatible with #{Mangadex::VERSION} but it looks like Mangadex is at #{version}",
16
- "[Warning] Check out #{Mangadex::Internal::Request::BASE_URI} for more information.",
17
- )
18
- end
19
-
20
- version
21
- end.call
22
- end
23
- end