mangadex 5.3.1.2 → 5.3.3.1

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: 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: []