pixiv_api 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +8 -0
- data/Guardfile +14 -0
- data/LICENSE.txt +21 -0
- data/README.md +33 -0
- data/Rakefile +6 -0
- data/lib/pixiv_api.rb +22 -0
- data/lib/pixiv_api/array_response.rb +23 -0
- data/lib/pixiv_api/authentication.rb +60 -0
- data/lib/pixiv_api/client.rb +72 -0
- data/lib/pixiv_api/configuration.rb +48 -0
- data/lib/pixiv_api/pixiv_blob.rb +41 -0
- data/lib/pixiv_api/request.rb +18 -0
- data/lib/pixiv_api/request/favorite_users.rb +19 -0
- data/lib/pixiv_api/request/friends.rb +9 -0
- data/lib/pixiv_api/request/novels.rb +21 -0
- data/lib/pixiv_api/request/profiles.rb +9 -0
- data/lib/pixiv_api/request/promotions.rb +20 -0
- data/lib/pixiv_api/request/ranking.rb +9 -0
- data/lib/pixiv_api/request/search.rb +10 -0
- data/lib/pixiv_api/request/signup.rb +25 -0
- data/lib/pixiv_api/request/trends.rb +16 -0
- data/lib/pixiv_api/request/upload_work.rb +27 -0
- data/lib/pixiv_api/request/users.rb +13 -0
- data/lib/pixiv_api/request/util.rb +38 -0
- data/lib/pixiv_api/request/version.rb +9 -0
- data/lib/pixiv_api/request/works.rb +21 -0
- data/lib/pixiv_api/response.rb +134 -0
- data/lib/pixiv_api/response/action.rb +23 -0
- data/lib/pixiv_api/response/friend.rb +25 -0
- data/lib/pixiv_api/response/identity.rb +12 -0
- data/lib/pixiv_api/response/illustration.rb +6 -0
- data/lib/pixiv_api/response/manga.rb +6 -0
- data/lib/pixiv_api/response/novel.rb +15 -0
- data/lib/pixiv_api/response/pagination.rb +25 -0
- data/lib/pixiv_api/response/promotion.rb +11 -0
- data/lib/pixiv_api/response/request.rb +26 -0
- data/lib/pixiv_api/response/signup_validation_result.rb +7 -0
- data/lib/pixiv_api/response/tag.rb +9 -0
- data/lib/pixiv_api/response/ugoira.rb +18 -0
- data/lib/pixiv_api/response/upload_status.rb +7 -0
- data/lib/pixiv_api/response/upload_token.rb +7 -0
- data/lib/pixiv_api/response/user.rb +15 -0
- data/lib/pixiv_api/response/version.rb +7 -0
- data/lib/pixiv_api/response/work.rb +46 -0
- data/lib/pixiv_api/version.rb +3 -0
- data/pixiv_api.gemspec +32 -0
- data/spec/pixiv_api/authentication_spec.rb +57 -0
- data/spec/pixiv_api/client_spec.rb +28 -0
- data/spec/pixiv_api/configuration_spec.rb +41 -0
- data/spec/pixiv_api/pixiv_blob_spec.rb +23 -0
- data/spec/pixiv_api/request/favorite_users_spec.rb +47 -0
- data/spec/pixiv_api/request/friends_spec.rb +14 -0
- data/spec/pixiv_api/request/novels_spec.rb +37 -0
- data/spec/pixiv_api/request/profiles_spec.rb +13 -0
- data/spec/pixiv_api/request/signup_spec.rb +76 -0
- data/spec/pixiv_api/request/upload_work_spec.rb +41 -0
- data/spec/pixiv_api/request/users_spec.rb +32 -0
- data/spec/pixiv_api/request/works_spec.rb +16 -0
- data/spec/pixiv_api/version_spec.rb +7 -0
- data/spec/pixiv_api_spec.rb +8 -0
- 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,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,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,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,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
|
data/pixiv_api.gemspec
ADDED
@@ -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
|