mangadex 5.3.1.2 → 5.3.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f849f066bfd4117f3a62b0712201ee6cafe769a7c2e6d6ef9d75789200accb9
4
- data.tar.gz: 74deaae68ac7efe1b3634495689350a34b0b2479508518a11ae8162207c41b55
3
+ metadata.gz: cdf99fecbef4c256aa1f0b739a7051d68f7f79a864f2525d7a56d5ee6a2cca79
4
+ data.tar.gz: 7250ded43bef9892e3d13323a1cea91c8f45378df330534f1a4f229575a1ebee
5
5
  SHA512:
6
- metadata.gz: daae07877b80764aa77d3aa3ed5e4332f93c60cd72a70c5aaba48d5de4a12c5f6259b19fae0dcbf9f11a7cfc24f4d4d7fd9c761a2ecacd0172bc968bde69670c
7
- data.tar.gz: 39515e57425a001d787a2bab769694e25c6da7aea8cbf7ffb1a3ee1d263cc7143576fbe916889180437d7c416ffaea392430d1a86080d135f40c2f4bd54d9df8
6
+ metadata.gz: ef23c65119a28a69e2c060b69361be24e3558cdce80b6bed93e1a0fc7463e7f87bca81b59c770c4fb378d68368c0da1713723523f4fee445d829ac9d4e0a973b
7
+ data.tar.gz: 58b0f5ee9763465a0801ebfbaf825c0009b12138bd20996ac34d5183c68a16ed6d515c8555e02b669c29cdbcb5e12916bb7adfec4d0769edbc7e793597d97334
@@ -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.1)
4
+ mangadex (5.3.3.1)
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
@@ -4,14 +4,23 @@ module Mangadex
4
4
  class Context
5
5
  extend T::Sig
6
6
 
7
+ DEFAULT_MANGADEX_CONTENT_RATING_VALUES = [
8
+ ContentRating::SAFE,
9
+ ContentRating::SUGGESTIVE,
10
+ ContentRating::EROTICA,
11
+ ].freeze
12
+
7
13
  @@user = nil
8
14
  @@version = nil
15
+ @@force_raw_requests = nil
16
+ @@tags = nil
17
+ @@allowed_content_ratings = DEFAULT_MANGADEX_CONTENT_RATING_VALUES
9
18
 
10
19
  sig { returns(T.nilable(String)) }
11
20
  def self.version
12
21
  return @@version unless @@version.nil?
13
22
 
14
- @@version = Mangadex::Api::Version.check_mangadex_version
23
+ @@version = Mangadex::Api::VersionChecker.check_mangadex_version
15
24
  end
16
25
 
17
26
  sig { returns(T.nilable(Mangadex::Api::User)) }
@@ -19,6 +28,18 @@ module Mangadex
19
28
  @@user&.with_valid_session
20
29
  end
21
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
+
22
43
  sig { params(user: T.nilable(T.any(Hash, Mangadex::Api::User, Mangadex::User))).void }
23
44
  def self.user=(user)
24
45
  if user.is_a?(Mangadex::Api::User)
@@ -29,7 +50,11 @@ module Mangadex
29
50
  data: user,
30
51
  )
31
52
  elsif user.is_a?(Hash)
32
- user = user.with_indifferent_access
53
+ user = Mangadex::Internal::Definition.validate(user, {
54
+ mangadex_user_id: { accepts: String, required: true },
55
+ session: { accepts: String },
56
+ refresh: { accepts: String },
57
+ })
33
58
 
34
59
  @@user = Mangadex::Api::User.new(
35
60
  user[:mangadex_user_id],
@@ -43,13 +68,9 @@ module Mangadex
43
68
 
44
69
  sig { params(user: T.nilable(T.any(Hash, Mangadex::Api::User, Mangadex::User)), block: T.proc.returns(T.untyped)).returns(T.untyped) }
45
70
  def self.with_user(user, &block)
46
- current_user = @@user
47
- @@user = user
48
- response = yield
49
- @@user = current_user
50
- response
51
- ensure
52
- @@user = current_user
71
+ temp_set_value("user", user) do
72
+ yield
73
+ end
53
74
  end
54
75
 
55
76
  sig { params(block: T.proc.returns(T.untyped)).returns(T.untyped) }
@@ -58,6 +79,59 @@ module Mangadex
58
79
  yield
59
80
  end
60
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
61
135
  end
62
136
  end
63
137
  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
@@ -3,7 +3,7 @@ require "psych"
3
3
 
4
4
  module Mangadex
5
5
  module Api
6
- class Version
6
+ class VersionChecker
7
7
  extend T::Sig
8
8
 
9
9
  sig { returns(T.nilable(String)) }
@@ -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
+ :nico_video,
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.
@@ -26,11 +26,14 @@ module Mangadex
26
26
  Mangadex::Internal::Request.get(
27
27
  '/chapter',
28
28
  Mangadex::Internal::Definition.chapter_list(args),
29
+ content_rating: true,
29
30
  )
30
31
  end
31
32
 
32
33
  sig { params(id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[Chapter]) }
33
34
  def self.get(id, **args)
35
+ Mangadex::Internal::Definition.must(id)
36
+
34
37
  Mangadex::Internal::Request.get(
35
38
  '/chapter/%{id}' % {id: id},
36
39
  Mangadex::Internal::Definition.validate(args, {
@@ -41,6 +44,8 @@ module Mangadex
41
44
 
42
45
  sig { params(id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[Chapter]) }
43
46
  def self.update(id, **args)
47
+ Mangadex::Internal::Definition.must(id)
48
+
44
49
  Mangadex::Internal::Request.put(
45
50
  '/chapter/%{id}' % {id: id},
46
51
  payload: Mangadex::Internal::Definition.validate(args, {
@@ -56,11 +61,17 @@ module Mangadex
56
61
 
57
62
  sig { params(id: String).returns(Hash) }
58
63
  def self.delete(id)
64
+ Mangadex::Internal::Definition.must(id)
65
+
59
66
  Mangadex::Internal::Request.delete(
60
67
  '/chapter/%{id}' % {id: id},
61
68
  )
62
69
  end
63
70
 
71
+ class << self
72
+ alias_method :view, :get
73
+ end
74
+
64
75
  sig { returns(String) }
65
76
  def title
66
77
  attributes&.title.presence || chapter.presence && "Chapter #{chapter}" || "N/A"
@@ -28,6 +28,11 @@ module Mangadex
28
28
  SCORES.keys.map { |key| ContentRating.new(key) }.select { |record| record <= content_rating }.sort
29
29
  end
30
30
 
31
+ sig { params(content_ratings: T::Array[T.any(T::Api::Text, T::Api::ContentRating)]).returns(T::Array[ContentRating]) }
32
+ def self.parse(content_ratings)
33
+ content_ratings.map { |content_rating| ContentRating.new(content_rating) }.uniq
34
+ end
35
+
31
36
  sig { params(value: T.any(T::Api::Text, T::Api::ContentRating)).void }
32
37
  def initialize(value)
33
38
  @value = ensure_value!(value.to_s)
@@ -64,7 +69,7 @@ module Mangadex
64
69
 
65
70
  private
66
71
 
67
- sig { params(value: T.any(T::Api::Text, T::Api::ContentRating)).void }
72
+ sig { params(value: T.any(T::Api::Text, T::Api::ContentRating)).returns(T.any(T::Api::Text, T::Api::ContentRating)) }
68
73
  def ensure_value!(value)
69
74
  return value if value.is_a?(ContentRating)
70
75
  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,14 +57,19 @@ 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),
65
+ content_rating: true,
57
66
  )
58
67
  end
59
68
 
60
69
  sig { params(id: String, list_id: String).returns(T::Boolean) }
61
70
  def self.add_manga(id, list_id:)
71
+ Mangadex::Internal::Definition.must(id)
72
+
62
73
  response = Mangadex::Internal::Request.post(
63
74
  '/manga/%{id}/list/%{list_id}' % {id: id, list_id: list_id},
64
75
  )
@@ -71,6 +82,8 @@ module Mangadex
71
82
 
72
83
  sig { params(id: String, list_id: String).returns(T::Boolean) }
73
84
  def self.remove_manga(id, list_id:)
85
+ Mangadex::Internal::Definition.must(id)
86
+
74
87
  response = Mangadex::Internal::Request.delete(
75
88
  '/manga/%{id}/list/%{list_id}' % {id: id, list_id: list_id},
76
89
  )
@@ -94,6 +107,8 @@ module Mangadex
94
107
 
95
108
  sig { params(user_id: String, args: T::Api::Arguments).returns(Mangadex::Api::Response[CustomList]) }
96
109
  def self.user_list(user_id, **args)
110
+ Mangadex::Internal::Definition.must(user_id)
111
+
97
112
  Mangadex::Internal::Request.get(
98
113
  '/user/%{id}/list' % {id: user_id},
99
114
  Mangadex::Internal::Definition.validate(args, {
@@ -103,6 +118,11 @@ module Mangadex
103
118
  )
104
119
  end
105
120
 
121
+ class << self
122
+ alias_method :view, :get
123
+ alias_method :edit, :update
124
+ end
125
+
106
126
  sig { params(id: String).returns(T::Boolean) }
107
127
  def add_manga(id)
108
128
  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
@@ -13,9 +13,9 @@ module Mangadex
13
13
  attr_accessor :path, :headers, :payload, :method, :raw
14
14
  attr_reader :response
15
15
 
16
- def self.get(path, params={}, auth: false, headers: nil, raw: false)
16
+ def self.get(path, params={}, auth: false, headers: nil, raw: false, content_rating: false)
17
17
  new(
18
- path_with_params(path, params),
18
+ path_with_params(path, params, content_rating),
19
19
  method: :get,
20
20
  headers: headers,
21
21
  payload: nil,
@@ -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
@@ -76,7 +78,8 @@ module Mangadex
76
78
 
77
79
  private
78
80
 
79
- def self.path_with_params(path, params)
81
+ def self.path_with_params(path, params, content_rating)
82
+ params = content_rating ? self.with_content_rating(params) : params
80
83
  return path if params.blank?
81
84
 
82
85
  params = params.deep_transform_keys do |key|
@@ -85,6 +88,14 @@ module Mangadex
85
88
  "#{path}?#{params.to_query}"
86
89
  end
87
90
 
91
+ def self.with_content_rating(data)
92
+ content_rating = data.has_key?(:content_rating) ? data[:content_rating] : []
93
+ Mangadex::Api::Context.allow_content_ratings(*content_rating) do
94
+ data[:content_rating] = Mangadex::Api::Context.allowed_content_ratings
95
+ end
96
+ data
97
+ end
98
+
88
99
  def request_url
89
100
  request_path = path.start_with?('/') ? path : "/#{path}"
90
101
  "#{BASE_URI}#{request_path}"
@@ -116,6 +127,12 @@ module Mangadex
116
127
 
117
128
  raise "Invalid method: #{method}. Must be one of: #{ALLOWED_METHODS}"
118
129
  end
130
+
131
+ def try_json(body)
132
+ JSON.parse(body)
133
+ rescue JSON::ParserError
134
+ body
135
+ end
119
136
  end
120
137
  end
121
138
  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
@@ -50,6 +50,7 @@ module Mangadex
50
50
  order: { accepts: Hash },
51
51
  includes: { accepts: Array, converts: to_a },
52
52
  }),
53
+ content_rating: true,
53
54
  )
54
55
  end
55
56
 
@@ -66,6 +67,8 @@ module Mangadex
66
67
 
67
68
  sig { params(id: String, args: T::Api::Arguments).returns(T::Api::MangaResponse) }
68
69
  def self.view(id, **args)
70
+ Mangadex::Internal::Definition.must(id)
71
+
69
72
  Mangadex::Internal::Request.get(
70
73
  '/manga/%{id}' % {id: id},
71
74
  Mangadex::Internal::Definition.validate(args, {
@@ -76,6 +79,8 @@ module Mangadex
76
79
 
77
80
  sig { params(id: String).returns(T.any(Hash, Mangadex::Api::Response)) }
78
81
  def self.unfollow(id)
82
+ Mangadex::Internal::Definition.must(id)
83
+
79
84
  Mangadex::Internal::Request.delete(
80
85
  '/manga/%{id}/follow' % {id: id},
81
86
  )
@@ -83,6 +88,8 @@ module Mangadex
83
88
 
84
89
  sig { params(id: String).returns(T.any(Hash, Mangadex::Api::Response)) }
85
90
  def self.follow(id)
91
+ Mangadex::Internal::Definition.must(id)
92
+
86
93
  Mangadex::Internal::Request.post(
87
94
  '/manga/%{id}/follow' % {id: id},
88
95
  )
@@ -90,9 +97,12 @@ module Mangadex
90
97
 
91
98
  sig { params(id: String, args: T::Api::Arguments).returns(T::Api::ChapterResponse) }
92
99
  def self.feed(id, **args)
100
+ Mangadex::Internal::Definition.must(id)
101
+
93
102
  Mangadex::Internal::Request.get(
94
103
  '/manga/%{id}/feed' % {id: id},
95
104
  Mangadex::Internal::Definition.chapter_list(args),
105
+ content_rating: true,
96
106
  )
97
107
  end
98
108
 
@@ -128,6 +138,8 @@ module Mangadex
128
138
 
129
139
  sig { params(id: String).returns(T::Api::GenericResponse) }
130
140
  def self.reading_status(id)
141
+ Mangadex::Internal::Definition.must(id)
142
+
131
143
  Mangadex::Internal::Request.get(
132
144
  '/manga/%{id}/status' % {id: id},
133
145
  )
@@ -135,6 +147,8 @@ module Mangadex
135
147
 
136
148
  sig { params(id: String, status: String).returns(T::Api::GenericResponse) }
137
149
  def self.update_reading_status(id, status)
150
+ Mangadex::Internal::Definition.must(id)
151
+
138
152
  Mangadex::Internal::Request.post(
139
153
  '/manga/%{id}/status' % {id: id},
140
154
  payload: Mangadex::Internal::Definition.validate({status: status}, {
@@ -149,11 +163,15 @@ module Mangadex
149
163
  # Untested API endpoints
150
164
  sig { params(id: String, args: T::Api::Arguments).returns(T::Api::MangaResponse) }
151
165
  def self.update(id, **args)
166
+ Mangadex::Internal::Definition.must(id)
167
+
152
168
  Mangadex::Internal::Request.put('/manga/%{id}' % {id: id}, payload: args)
153
169
  end
154
170
 
155
171
  sig { params(id: String).returns(Hash) }
156
172
  def self.delete(id)
173
+ Mangadex::Internal::Definition.must(id)
174
+
157
175
  Mangadex::Internal::Request.delete(
158
176
  '/manga/%{id}' % {id: id},
159
177
  )
@@ -169,6 +187,8 @@ module Mangadex
169
187
 
170
188
  class << self
171
189
  alias_method :aggregate, :volumes_and_chapters
190
+ alias_method :get, :view
191
+ alias_method :edit, :update
172
192
  end
173
193
 
174
194
  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,7 @@ 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
21
  )
22
22
  end
23
23
  ChapterResponse = T.type_alias do
data/lib/mangadex/tag.rb CHANGED
@@ -3,6 +3,11 @@ module Mangadex
3
3
  class Tag < MangadexObject
4
4
  has_attributes :name, :description, :group, :version
5
5
 
6
+ sig { returns(Mangadex::Api::Response[Mangadex::Tag]) }
7
+ def self.list
8
+ Mangadex::Manga.tag_list
9
+ end
10
+
6
11
  def self.attributes_to_inspect
7
12
  %i(name)
8
13
  end
@@ -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
@@ -11,6 +11,7 @@ module Mangadex
11
11
  Mangadex::Internal::Request.get(
12
12
  '/user/follows/manga/feed',
13
13
  Mangadex::Internal::Definition.chapter_list(args),
14
+ content_rating: true,
14
15
  auth: true,
15
16
  )
16
17
  end
@@ -30,6 +31,8 @@ module Mangadex
30
31
 
31
32
  sig { params(id: String).returns(T::Boolean) }
32
33
  def self.follows_group(id)
34
+ Mangadex::Internal::Definition.must(id)
35
+
33
36
  data = Mangadex::Internal::Request.get(
34
37
  '/user/follows/group/%{id}' % {id: id},
35
38
  raw: true,
@@ -55,6 +58,8 @@ module Mangadex
55
58
 
56
59
  sig { params(id: String).returns(T::Boolean) }
57
60
  def self.follows_user(id)
61
+ Mangadex::Internal::Definition.must(id)
62
+
58
63
  return if Mangadex::Api::Context.user.nil?
59
64
 
60
65
  data = Mangadex::Internal::Request.get(
@@ -83,6 +88,8 @@ module Mangadex
83
88
 
84
89
  sig { params(id: String).returns(T::Boolean) }
85
90
  def self.follows_manga(id)
91
+ Mangadex::Internal::Definition.must(id)
92
+
86
93
  return if Mangadex::Api::Context.user.nil?
87
94
 
88
95
  data = Mangadex::Internal::Request.get(
@@ -3,8 +3,8 @@ module Mangadex
3
3
  module Version
4
4
  MAJOR = "5"
5
5
  MINOR = "3"
6
- TINY = "1"
7
- PATCH = "2"
6
+ TINY = "3"
7
+ PATCH = "1"
8
8
 
9
9
  STRING = [MAJOR, MINOR, TINY].compact.join('.')
10
10
  FULL = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
data/mangadex.gemspec CHANGED
@@ -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.2
4
+ version: 5.3.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akinyele Cafe-Febrissy
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-23 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
@@ -136,13 +150,14 @@ dependencies:
136
150
  - - ">="
137
151
  - !ruby/object:Gem::Version
138
152
  version: '0'
139
- description:
153
+ description:
140
154
  email:
141
155
  - me@akinyele.ca
142
156
  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"
@@ -221,7 +236,7 @@ homepage: https://github.com/thedrummeraki/mangadex
221
236
  licenses:
222
237
  - MIT
223
238
  metadata: {}
224
- post_install_message:
239
+ post_install_message:
225
240
  rdoc_options: []
226
241
  require_paths:
227
242
  - lib
@@ -237,7 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
237
252
  version: '0'
238
253
  requirements: []
239
254
  rubygems_version: 3.2.15
240
- signing_key:
255
+ signing_key:
241
256
  specification_version: 4
242
257
  summary: Your next favourite Ruby gem for interacting with Mangadex.org
243
258
  test_files: []