pixiv_api 0.0.4

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.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +8 -0
  6. data/Guardfile +14 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +33 -0
  9. data/Rakefile +6 -0
  10. data/lib/pixiv_api.rb +22 -0
  11. data/lib/pixiv_api/array_response.rb +23 -0
  12. data/lib/pixiv_api/authentication.rb +60 -0
  13. data/lib/pixiv_api/client.rb +72 -0
  14. data/lib/pixiv_api/configuration.rb +48 -0
  15. data/lib/pixiv_api/pixiv_blob.rb +41 -0
  16. data/lib/pixiv_api/request.rb +18 -0
  17. data/lib/pixiv_api/request/favorite_users.rb +19 -0
  18. data/lib/pixiv_api/request/friends.rb +9 -0
  19. data/lib/pixiv_api/request/novels.rb +21 -0
  20. data/lib/pixiv_api/request/profiles.rb +9 -0
  21. data/lib/pixiv_api/request/promotions.rb +20 -0
  22. data/lib/pixiv_api/request/ranking.rb +9 -0
  23. data/lib/pixiv_api/request/search.rb +10 -0
  24. data/lib/pixiv_api/request/signup.rb +25 -0
  25. data/lib/pixiv_api/request/trends.rb +16 -0
  26. data/lib/pixiv_api/request/upload_work.rb +27 -0
  27. data/lib/pixiv_api/request/users.rb +13 -0
  28. data/lib/pixiv_api/request/util.rb +38 -0
  29. data/lib/pixiv_api/request/version.rb +9 -0
  30. data/lib/pixiv_api/request/works.rb +21 -0
  31. data/lib/pixiv_api/response.rb +134 -0
  32. data/lib/pixiv_api/response/action.rb +23 -0
  33. data/lib/pixiv_api/response/friend.rb +25 -0
  34. data/lib/pixiv_api/response/identity.rb +12 -0
  35. data/lib/pixiv_api/response/illustration.rb +6 -0
  36. data/lib/pixiv_api/response/manga.rb +6 -0
  37. data/lib/pixiv_api/response/novel.rb +15 -0
  38. data/lib/pixiv_api/response/pagination.rb +25 -0
  39. data/lib/pixiv_api/response/promotion.rb +11 -0
  40. data/lib/pixiv_api/response/request.rb +26 -0
  41. data/lib/pixiv_api/response/signup_validation_result.rb +7 -0
  42. data/lib/pixiv_api/response/tag.rb +9 -0
  43. data/lib/pixiv_api/response/ugoira.rb +18 -0
  44. data/lib/pixiv_api/response/upload_status.rb +7 -0
  45. data/lib/pixiv_api/response/upload_token.rb +7 -0
  46. data/lib/pixiv_api/response/user.rb +15 -0
  47. data/lib/pixiv_api/response/version.rb +7 -0
  48. data/lib/pixiv_api/response/work.rb +46 -0
  49. data/lib/pixiv_api/version.rb +3 -0
  50. data/pixiv_api.gemspec +32 -0
  51. data/spec/pixiv_api/authentication_spec.rb +57 -0
  52. data/spec/pixiv_api/client_spec.rb +28 -0
  53. data/spec/pixiv_api/configuration_spec.rb +41 -0
  54. data/spec/pixiv_api/pixiv_blob_spec.rb +23 -0
  55. data/spec/pixiv_api/request/favorite_users_spec.rb +47 -0
  56. data/spec/pixiv_api/request/friends_spec.rb +14 -0
  57. data/spec/pixiv_api/request/novels_spec.rb +37 -0
  58. data/spec/pixiv_api/request/profiles_spec.rb +13 -0
  59. data/spec/pixiv_api/request/signup_spec.rb +76 -0
  60. data/spec/pixiv_api/request/upload_work_spec.rb +41 -0
  61. data/spec/pixiv_api/request/users_spec.rb +32 -0
  62. data/spec/pixiv_api/request/works_spec.rb +16 -0
  63. data/spec/pixiv_api/version_spec.rb +7 -0
  64. data/spec/pixiv_api_spec.rb +8 -0
  65. metadata +275 -0
@@ -0,0 +1,25 @@
1
+ module PixivApi
2
+ class Response
3
+ class Pagination < Response
4
+ def self.from_response(response, *attributes)
5
+ new(response, *attributes)
6
+ end
7
+
8
+ def self.define_pagination_url(*attrs)
9
+ attrs.each do |attr|
10
+ define_method "#{attr}_url" do
11
+ if self[attr]
12
+ params = @request.params.merge('page' => self[attr])
13
+ url = @request.url
14
+ url.query = URI.encode_www_form(params)
15
+ url
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ attr_reader :previous, :next, :current, :per_page, :total, :pages
22
+ define_pagination_url :previous, :next, :current
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ module PixivApi
2
+ class Response
3
+ class Promotion < Response
4
+ def self.from_response(response, attributes)
5
+ new(response, attributes)
6
+ end
7
+
8
+ attr_reader :px_user_external_site_ads_id, :user_id, :site_id, :ads
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ module PixivApi
2
+ class Response
3
+ class Request
4
+ def initialize(response)
5
+ @response = response
6
+ @env = response.response.env
7
+ end
8
+
9
+ def full_url
10
+ @env.url
11
+ end
12
+
13
+ def url
14
+ URI(full_url.to_s.gsub(/\?.*$/, ''))
15
+ end
16
+
17
+ def query
18
+ @env.url.query
19
+ end
20
+
21
+ def params
22
+ Rack::Utils.parse_query(query)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,7 @@
1
+ module PixivApi
2
+ class Response
3
+ class SignupValidationResult < Response
4
+ attr_reader :is_valid, :mail_address, :pixiv_id, :user_name, :password, :password_again, :sex, :birthday
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module PixivApi
2
+ class Response
3
+ class Tag < Response
4
+ attr_reader :name, :count, :total_count
5
+
6
+ define_attributes_method :works, Response::Work
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ module PixivApi
2
+ class Response
3
+ class Ugoira < Work
4
+ def frames
5
+ @attributes['metadata']['frames']
6
+ end
7
+
8
+ def zip_urls
9
+ @attributes['metadata']['zip_urls'].map do |zip_urls, memo|
10
+ zip_urls.each_with_object({}) do |(key, value), memo|
11
+ memo[key] = blob_image_url(value)
12
+ end
13
+ end
14
+ end
15
+ memoize(:zip_urls)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ module PixivApi
2
+ class Response
3
+ class UploadStatus < Response
4
+ attr_reader :status, :id, :title, :publicity, :age_limit
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module PixivApi
2
+ class Response
3
+ class UploadToken < Response
4
+ attr_reader :upload_token
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ module PixivApi
2
+ class Response
3
+ class User < Identity
4
+ attr_reader :id, :account, :name, :is_following, :is_follower,
5
+ :is_friend, :is_premium, :stats, :profile, :email
6
+
7
+ define_blob_method :profile_image_urls
8
+
9
+ def avatar_url
10
+ blob_profile_image_urls['px_50x50']
11
+ end
12
+ memoize(:avatar_url)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module PixivApi
2
+ class Response
3
+ class Version < Response
4
+ attr_reader :version
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,46 @@
1
+ module PixivApi
2
+ class Response
3
+ class Work < Identity
4
+ def self.from_response(response, *args)
5
+ attributes = args.extract_options!
6
+
7
+ base = case attributes['type']
8
+ when 'illustration'
9
+ Illustration
10
+ when 'manga'
11
+ Manga
12
+ when 'ugoira'
13
+ Ugoira
14
+ else
15
+ raise NotImplementedError, 'unknown type given.'
16
+ end
17
+
18
+ base.new(response, attributes)
19
+ end
20
+
21
+ attr_reader :id, :age_limit, :caption, :favorite_id,
22
+ :height, :is_linked, :is_manga, :publicity,
23
+ :stats, :title, :tools, :width, :page_count,
24
+ :book_style, :type, :metadata
25
+
26
+ define_attribute_method :user, Response::User
27
+
28
+ define_blob_method :image_urls
29
+
30
+ define_time_method :created_time, :reuploaded_time
31
+
32
+ def pages
33
+ @attributes['metadata']['pages'].map do |base, memo|
34
+ base['image_urls'].each_with_object({}) do |(key, value), memo|
35
+ memo[key] = blob_image_url(value)
36
+ end
37
+ end
38
+ rescue
39
+ # XXX: workの種類によってはエラーが起こる?
40
+ []
41
+ end
42
+
43
+ memoize(:pages)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ module PixivApi
2
+ VERSION = '0.0.4'
3
+ end
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pixiv_api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'pixiv_api'
8
+ spec.version = PixivApi::VERSION
9
+ spec.authors = ['alpaca-tc']
10
+ spec.email = ['alpaca-tc@alpaca.tc']
11
+
12
+ spec.summary = %q{pixiv public api client}
13
+ spec.description = %q{pixiv public api client.}
14
+ spec.homepage = 'https://github.com/pixiv/pixiv-api-ruby'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.test_files = Dir['spec/**/*_spec.rb']
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'oauth2', '~> 1.0'
22
+ spec.add_dependency 'memoizable', '~> 0.4'
23
+ spec.add_dependency 'activesupport', '>= 4.0'
24
+ spec.add_development_dependency 'bundler', '~> 1.10'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'rspec', '~> 3.3'
27
+ spec.add_development_dependency 'guard', '~> 2.13'
28
+ spec.add_development_dependency 'guard-rspec', '~> 4.6'
29
+ spec.add_development_dependency 'vcr', '~> 2.9'
30
+ spec.add_development_dependency 'webmock', '~> 1.21'
31
+ spec.add_development_dependency 'pry', '~> 0.10'
32
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe PixivApi::Authentication do
4
+ stub_pixiv_api_configuration
5
+
6
+ let(:initialized) { described_class.new(id: id, password: password) }
7
+ let(:id) { 'gami' }
8
+ let(:password) { 'password' }
9
+
10
+ shared_examples_for 'a token response' do
11
+ it 'contains tokens' do
12
+ expect(authentication.body['access_token']).to_not be_nil
13
+ expect(authentication.body['refresh_token']).to_not be_nil
14
+ expect(authentication.body['expires_in']).to_not be_nil
15
+ expect(authentication.body['scope']).to_not be_nil
16
+ end
17
+ end
18
+
19
+ describe '#initialize' do
20
+ xcontext 'not stubbed request' do
21
+ subject(:authentication) do
22
+ vcr_turned_off! do
23
+ initialized
24
+ end
25
+ end
26
+ let(:password) { "Write gami's password here" } # DO NOT commit this line.
27
+
28
+ it_behaves_like 'a token response'
29
+ end
30
+
31
+ context 'stubbed request' do
32
+ subject(:authentication) do
33
+ cassette cassette_path do
34
+ initialized
35
+ end
36
+ end
37
+
38
+ context 'when fail to authenticate user' do
39
+ let(:cassette_path) { 'authentication_failure' }
40
+ it { expect { authentication }.to raise_error(described_class::InvalidAuthError) }
41
+ end
42
+
43
+ context 'when authenticated user was successfully' do
44
+ let(:cassette_path) { 'authentication_success' }
45
+ it_behaves_like 'a token response'
46
+ end
47
+ end
48
+ end
49
+
50
+ describe '#to_client' do
51
+ subject(:authentication) do
52
+ cassette('authentication_success') { initialized }.to_client
53
+ end
54
+
55
+ it { is_expected.to be_a(PixivApi::Client) }
56
+ end
57
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe PixivApi::Client do
4
+ subject(:client) do
5
+ described_class.new(
6
+ access_token: access_token,
7
+ refresh_token: refresh_token,
8
+ expires_at: expires_at
9
+ )
10
+ end
11
+
12
+ let(:access_token) { 'access_token' }
13
+ let(:refresh_token) { 'refresh_token' }
14
+ let(:expires_at) { Time.now.to_i }
15
+
16
+ context 'when configuration is not completed' do
17
+ describe '#initialize' do
18
+ it 'initializes oauth access token' do
19
+ expect { client }.to raise_error(PixivApi::Configuration::MissingConfigurationError)
20
+ end
21
+ end
22
+ end
23
+
24
+ context 'when configuration is completed' do
25
+ stub_pixiv_api_configuration
26
+ it { expect { subject }.to_not raise_error }
27
+ end
28
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe PixivApi::Configuration do
4
+ let(:configuration) { described_class.new }
5
+
6
+ describe '#require_keys!' do
7
+ subject do
8
+ -> { configuration.require_keys! }
9
+ end
10
+
11
+ context 'when missing required keys' do
12
+ it { is_expected.to raise_error(described_class::MissingConfigurationError) }
13
+ end
14
+
15
+ context 'when configuration contains required keys' do
16
+ before do
17
+ %i(client_id client_secret site authorize_url token_url).each do |key|
18
+ configuration[key] = true
19
+ end
20
+ end
21
+
22
+ it { is_expected.to_not raise_error }
23
+ end
24
+ end
25
+
26
+ describe '#[]' do
27
+ subject do
28
+ -> { configuration[key] = true }
29
+ end
30
+
31
+ context 'given unknown key' do
32
+ let(:key) { :unknown }
33
+ it { is_expected.to raise_error(described_class::InvalidKeyError) }
34
+ end
35
+
36
+ context 'given known key' do
37
+ let(:key) { :client_id }
38
+ it { is_expected.to_not raise_error }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe PixivApi::PixivBlob do
4
+ let(:url) { 'http://i2.pixiv.net/c/600x600/img-master/img/2015/07/26/21/49/36/51625741_p0_master1200.jpg' }
5
+ subject(:blob) { described_class.new(url) }
6
+
7
+ describe '#read' do
8
+ subject { blob.read }
9
+
10
+ it 'returns content' do
11
+ is_expected.to_not be_nil
12
+ end
13
+ end
14
+
15
+ describe '#to_path' do
16
+ subject { blob.to_path }
17
+
18
+ it 'returns content' do
19
+ is_expected.to_not be_nil
20
+ expect(File).to be_exists(subject)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe PixivApi::Request::FavoriteUsers do
4
+ stub_pixiv_api_client
5
+ let(:user_id) { 341433 }
6
+
7
+ describe '#favorite_users' do
8
+ subject do
9
+ cassette 'favorite_users_success' do
10
+ client.favorite_users
11
+ end
12
+ end
13
+
14
+ it 'builds array of PixivApiResponse::User' do
15
+ is_expected.to all(be_a(PixivApi::Response::User))
16
+ end
17
+
18
+ it_behaves_like 'contained pagination'
19
+ end
20
+
21
+ describe '#delete_favorite_users' do
22
+ subject do
23
+ cassette cassettle_path do
24
+ client.delete_favorite_users(user_ids: [user_id])
25
+ end
26
+ end
27
+
28
+ context 'when deleted favorite user was successfully' do
29
+ let(:cassettle_path) { 'delete_favorite_users_success' }
30
+
31
+ it 'builds array of PixivApiResponse::Action' do
32
+ is_expected.to be_a(PixivApi::Response::Action)
33
+ expect(subject).to be_success
34
+ end
35
+ end
36
+ end
37
+
38
+ describe '#favorite_user' do
39
+ subject do
40
+ cassette 'favorite_user_success' do
41
+ client.favorite_user(user_id: user_id, publicity: 'public')
42
+ end
43
+ end
44
+
45
+ it { is_expected.to be_a(PixivApi::Response::Action) }
46
+ end
47
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe PixivApi::Request::Friends do
4
+ stub_pixiv_api_client
5
+
6
+ describe '#friends' do
7
+ subject do
8
+ cassette('users_friends_success') { client.friends }
9
+ end
10
+
11
+ it { is_expected.to all(be_a(PixivApi::Response::Friend)) }
12
+ it_behaves_like 'contained pagination'
13
+ end
14
+ end