qiita-export 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -3
- data/lib/qiita-export.rb +2 -1
- data/lib/qiita-export/config.rb +44 -13
- data/lib/qiita-export/exporter.rb +3 -1
- data/lib/qiita-export/fetcher/api_end_point.rb +41 -0
- data/lib/qiita-export/fetcher/api_fetcher.rb +0 -10
- data/lib/qiita-export/fetcher/base.rb +9 -1
- data/lib/qiita-export/fetcher/kobito_fetcher.rb +2 -1
- data/lib/qiita-export/fetcher/pagination_fetcher.rb +45 -0
- data/lib/qiita-export/fetcher/url_fetcher.rb +2 -1
- data/lib/qiita-export/version.rb +1 -1
- metadata +4 -3
- data/lib/qiita-export/fetcher/user_fetcher.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 821a3351e6e0d5ae3a620e12828d645e9b985678
|
4
|
+
data.tar.gz: 18d4e090f2d8f10f06e81344d9f13772cdace11c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1551e1b916754310037f0993f8ed1048bd27fdd11f7eb5b57e209e68799ea30e5a509d69846183eae8ea7105703309814a9c869742ce138013ef24245addd994
|
7
|
+
data.tar.gz: acf2bea60094739fdc10959eaf703ddcf27381fd587de0db4900de29482b008a169188fdf9415908c2e8fe1646d2b55dba358145efd5a3c586fe5b0e72bff865
|
data/README.md
CHANGED
@@ -4,10 +4,10 @@ export tool for Qiita(http://qiita.com/).
|
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
-
Add this line to your
|
7
|
+
Add this line to your Gemfile:
|
8
8
|
|
9
9
|
```ruby
|
10
|
-
gem '
|
10
|
+
gem 'qiita-export'
|
11
11
|
```
|
12
12
|
|
13
13
|
And then execute:
|
@@ -19,7 +19,7 @@ $ bundle
|
|
19
19
|
Or install it yourself as:
|
20
20
|
|
21
21
|
```
|
22
|
-
$ gem install
|
22
|
+
$ gem install qiita-export
|
23
23
|
```
|
24
24
|
|
25
25
|
## Usage
|
@@ -31,10 +31,12 @@ Usage: qiita-export [options]
|
|
31
31
|
-U, --user-id=user_id specify the userid for the Qiita.
|
32
32
|
-k, --kobito=[Kobito.db] export Kobito.app database.
|
33
33
|
-t, --team=teamname export Qiita Team articles only.
|
34
|
+
-T, --team-all export Qiita Team all articles.
|
34
35
|
-i, --image export with images.
|
35
36
|
-h, --html export in html format(experimental).
|
36
37
|
-o, --output-dir=dirpath specify the full path of destination directory.
|
37
38
|
-a, --api-token=token specify API token for Qiita.
|
39
|
+
-e, --exclude-pattern=regexp specify the regexp pattern to exclude article title.
|
38
40
|
```
|
39
41
|
|
40
42
|
## Contributing
|
data/lib/qiita-export.rb
CHANGED
@@ -3,8 +3,9 @@ require 'qiita-export/image'
|
|
3
3
|
require 'qiita-export/article'
|
4
4
|
require 'qiita-export/config'
|
5
5
|
require 'qiita-export/exporter'
|
6
|
+
require 'qiita-export/fetcher/api_end_point'
|
6
7
|
require 'qiita-export/fetcher/base'
|
7
8
|
require 'qiita-export/fetcher/kobito_fetcher'
|
8
9
|
require 'qiita-export/fetcher/api_fetcher'
|
9
10
|
require 'qiita-export/fetcher/url_fetcher'
|
10
|
-
require 'qiita-export/fetcher/
|
11
|
+
require 'qiita-export/fetcher/pagination_fetcher'
|
data/lib/qiita-export/config.rb
CHANGED
@@ -6,6 +6,7 @@ module QiitaExport
|
|
6
6
|
HOME_CONFIG_FILE = "~/.qiita-exportrc"
|
7
7
|
LOCAL_CONFIG_FILE = "./.qiita-exportrc"
|
8
8
|
|
9
|
+
DEFAULT_HOST = "qiita.com"
|
9
10
|
DEFAULT_USER_AGENT = "QiitaExport Gem #{QiitaExport::VERSION}"
|
10
11
|
|
11
12
|
DEFAULT_HEADER = {
|
@@ -19,15 +20,17 @@ module QiitaExport
|
|
19
20
|
@option = {}
|
20
21
|
@parser = OptionParser.new do |opt|
|
21
22
|
opt.version = QiitaExport::VERSION
|
22
|
-
opt.on('-u', '--url=url',
|
23
|
-
opt.on('-l', '--url-list=filepath',
|
24
|
-
opt.on('-U', '--user-id=user_id',
|
25
|
-
opt.on('-k', '--kobito=[Kobito.db]',
|
26
|
-
opt.on('-t', '--team=teamname',
|
27
|
-
opt.on('-
|
28
|
-
opt.on('-
|
29
|
-
opt.on('-
|
30
|
-
opt.on('-
|
23
|
+
opt.on('-u', '--url=url', 'specify the URL for the Qiita(or Qiita Team).') { |v| @option[:url] = v }
|
24
|
+
opt.on('-l', '--url-list=filepath', 'specify the file path of the URL list.') { |v| @option[:'url-list'] = v }
|
25
|
+
opt.on('-U', '--user-id=user_id', 'specify the userid for the Qiita.') { |v| @option[:'user-id'] = v }
|
26
|
+
opt.on('-k', '--kobito=[Kobito.db]', 'export Kobito.app database.') { |v| @option[:kobito] = v }
|
27
|
+
opt.on('-t', '--team=teamname', 'export Qiita Team articles only.') { |v| @option[:team] = v }
|
28
|
+
opt.on('-T', '--team-all', 'export Qiita Team all articles.') { |v| @option[:'team-all'] = v }
|
29
|
+
opt.on('-i', '--image', 'export with images.') { |v| @option[:image] = v }
|
30
|
+
opt.on('-h', '--html', 'export in html format(experimental).') { |v| @option[:html] = v }
|
31
|
+
opt.on('-o', '--output-dir=dirpath', 'specify the full path of destination directory.') { |v| @option[:'output-dir'] = v }
|
32
|
+
opt.on('-a', '--api-token=token', 'specify API token for Qiita.') { |v| @option[:'api-token'] = v }
|
33
|
+
opt.on('-e', '--exclude-pattern=regexp', 'specify the regexp pattern to exclude article title.') { |v| @option[:'exclude-pattern'] = v }
|
31
34
|
end
|
32
35
|
|
33
36
|
# load home config
|
@@ -62,6 +65,18 @@ module QiitaExport
|
|
62
65
|
if kobito? && api?
|
63
66
|
fail ArgumentError.new("if you specify option --kobito, you cannot specify option --url, --url-list and --user-id.")
|
64
67
|
end
|
68
|
+
|
69
|
+
if !kobito? && !api?
|
70
|
+
fail ArgumentError.new("one of the required options --kobito, --url, --url-list and --user-id must be specified.")
|
71
|
+
end
|
72
|
+
|
73
|
+
if !kobito? && team? && !has_api_token?
|
74
|
+
fail ArgumentError.new("if you specify option --team, option --api-token is required.")
|
75
|
+
end
|
76
|
+
|
77
|
+
if team_all? && !team?
|
78
|
+
fail ArgumentError.new("if you specify option --team-all, option --team is required.")
|
79
|
+
end
|
65
80
|
end
|
66
81
|
|
67
82
|
def kobito?
|
@@ -69,7 +84,7 @@ module QiitaExport
|
|
69
84
|
end
|
70
85
|
|
71
86
|
def api?
|
72
|
-
present?(@option[:url]) || present?(@option[:'url-list']) || present?(@option[:'user-id'])
|
87
|
+
present?(@option[:url]) || present?(@option[:'url-list']) || present?(@option[:'user-id']) || team_all?
|
73
88
|
end
|
74
89
|
|
75
90
|
def user?
|
@@ -80,6 +95,10 @@ module QiitaExport
|
|
80
95
|
present?(@option[:team])
|
81
96
|
end
|
82
97
|
|
98
|
+
def team_all?
|
99
|
+
@option.key?(:'team-all')
|
100
|
+
end
|
101
|
+
|
83
102
|
def file_export?
|
84
103
|
present?(@option[:'output-dir'])
|
85
104
|
end
|
@@ -98,10 +117,10 @@ module QiitaExport
|
|
98
117
|
|
99
118
|
DOMAIN_PATTERN = Regexp.new("https?://([^/]+)/")
|
100
119
|
def team_name(url = nil)
|
101
|
-
if (
|
102
|
-
@option[:team]
|
103
|
-
elsif api? && team_url?(url)
|
120
|
+
if present?(url)
|
104
121
|
url.match(DOMAIN_PATTERN)[1].split('.')[0]
|
122
|
+
elsif team?
|
123
|
+
@option[:team]
|
105
124
|
else
|
106
125
|
""
|
107
126
|
end
|
@@ -131,10 +150,22 @@ module QiitaExport
|
|
131
150
|
end
|
132
151
|
end
|
133
152
|
|
153
|
+
def api_domain(url = nil)
|
154
|
+
if url.nil?
|
155
|
+
team? ? "#{team_name}.#{DEFAULT_HOST}" : DEFAULT_HOST
|
156
|
+
else
|
157
|
+
URI.parse(url).host
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
134
161
|
def api_token
|
135
162
|
@option[:'api-token']
|
136
163
|
end
|
137
164
|
|
165
|
+
def exclude_pattern
|
166
|
+
@option[:'exclude-pattern']
|
167
|
+
end
|
168
|
+
|
138
169
|
def has_api_token?
|
139
170
|
present?(@option[:'api-token'])
|
140
171
|
end
|
@@ -22,7 +22,9 @@ module QiitaExport
|
|
22
22
|
if Config.kobito?
|
23
23
|
QiitaExport::Fetcher::KobitoFetcher.new
|
24
24
|
elsif Config.user?
|
25
|
-
QiitaExport::Fetcher::
|
25
|
+
QiitaExport::Fetcher::PaginationFetcher.new(:user)
|
26
|
+
elsif Config.team_all?
|
27
|
+
QiitaExport::Fetcher::PaginationFetcher.new(:team)
|
26
28
|
else
|
27
29
|
QiitaExport::Fetcher::UrlFetcher.new
|
28
30
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module QiitaExport::Fetcher
|
4
|
+
class ApiEndPoint
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@config = ::QiitaExport::Config
|
8
|
+
end
|
9
|
+
|
10
|
+
def next_page(page)
|
11
|
+
raise NotImplementedError.new("You must implement #{self.class}##{__method__}")
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.instance(end_point_sym)
|
15
|
+
case end_point_sym
|
16
|
+
when :user
|
17
|
+
UserEndPoint.new
|
18
|
+
when :team
|
19
|
+
TeamEndPoint.new
|
20
|
+
else
|
21
|
+
raise ArgumentError("unsupported endpont: #{end_point_sym}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class UserEndPoint < ApiEndPoint
|
27
|
+
PER_PAGE = 100
|
28
|
+
|
29
|
+
def next_page(page)
|
30
|
+
"https://#{@config.api_domain}/api/v2/users/#{@config.user_id}/items?page=#{page}&per_page=#{PER_PAGE}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class TeamEndPoint < ApiEndPoint
|
35
|
+
PER_PAGE = 100
|
36
|
+
|
37
|
+
def next_page(page)
|
38
|
+
"https://#{@config.api_domain}/api/v2/items?page=#{page}&per_page=#{PER_PAGE}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -5,8 +5,6 @@ require 'uri'
|
|
5
5
|
module QiitaExport::Fetcher
|
6
6
|
class ApiFetcher < Base
|
7
7
|
|
8
|
-
DEFAULT_HOST = "qiita.com"
|
9
|
-
|
10
8
|
protected
|
11
9
|
|
12
10
|
def to_article(res)
|
@@ -30,13 +28,5 @@ module QiitaExport::Fetcher
|
|
30
28
|
has_api_token? ? auth_header : default_header
|
31
29
|
end
|
32
30
|
|
33
|
-
def api_domain(url = nil)
|
34
|
-
if url.nil?
|
35
|
-
team? ? "#{team_name}.#{DEFAULT_HOST}" : DEFAULT_HOST
|
36
|
-
else
|
37
|
-
URI.parse(url).host
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
31
|
end
|
42
32
|
end
|
@@ -8,7 +8,8 @@ module QiitaExport::Fetcher
|
|
8
8
|
def_delegators :@config, :kobito?, :kobito_db, :file_export?,
|
9
9
|
:export_dir_path, :team?, :team_name,
|
10
10
|
:article_urls, :has_api_token?, :api_token,
|
11
|
-
:user_id, :default_header, :auth_header
|
11
|
+
:user_id, :default_header, :auth_header,
|
12
|
+
:api_domain
|
12
13
|
|
13
14
|
def initialize
|
14
15
|
@config = ::QiitaExport::Config
|
@@ -18,5 +19,12 @@ module QiitaExport::Fetcher
|
|
18
19
|
raise NotImplementedError.new("You must implement #{self.class}##{__method__}")
|
19
20
|
end
|
20
21
|
|
22
|
+
def exclude?(title)
|
23
|
+
if !@config.exclude_pattern.nil? && /#{@config.exclude_pattern}/ =~ title
|
24
|
+
return true
|
25
|
+
end
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
21
29
|
end
|
22
30
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'json'
|
3
|
+
require 'open-uri'
|
4
|
+
|
5
|
+
module QiitaExport::Fetcher
|
6
|
+
class PaginationFetcher < ApiFetcher
|
7
|
+
|
8
|
+
PER_PAGE = 100
|
9
|
+
|
10
|
+
def initialize(endpoint_sym)
|
11
|
+
super()
|
12
|
+
@endpoint = ApiEndPoint.instance(endpoint_sym)
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_articles
|
16
|
+
articles = []
|
17
|
+
page = 1
|
18
|
+
while true
|
19
|
+
api_responses = paginate_articles(page)
|
20
|
+
break if api_responses.empty?
|
21
|
+
|
22
|
+
api_responses.each do |api_response|
|
23
|
+
article = to_article(api_response)
|
24
|
+
articles << article unless exclude?(article.title)
|
25
|
+
end
|
26
|
+
|
27
|
+
page += 1
|
28
|
+
sleep(0.3)
|
29
|
+
end
|
30
|
+
articles.sort { |a, b| a.created_at <=> b.created_at }
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def paginate_articles(page)
|
36
|
+
url = @endpoint.next_page(page)
|
37
|
+
open(@endpoint.next_page(page), request_header) do |io|
|
38
|
+
JSON.parse(io.read)
|
39
|
+
end
|
40
|
+
rescue => e
|
41
|
+
$stderr.puts "#{e} : #{url}"
|
42
|
+
raise
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/qiita-export/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qiita-export
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shin Akiyama
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sqlite3
|
@@ -84,11 +84,12 @@ files:
|
|
84
84
|
- lib/qiita-export/article.rb
|
85
85
|
- lib/qiita-export/config.rb
|
86
86
|
- lib/qiita-export/exporter.rb
|
87
|
+
- lib/qiita-export/fetcher/api_end_point.rb
|
87
88
|
- lib/qiita-export/fetcher/api_fetcher.rb
|
88
89
|
- lib/qiita-export/fetcher/base.rb
|
89
90
|
- lib/qiita-export/fetcher/kobito_fetcher.rb
|
91
|
+
- lib/qiita-export/fetcher/pagination_fetcher.rb
|
90
92
|
- lib/qiita-export/fetcher/url_fetcher.rb
|
91
|
-
- lib/qiita-export/fetcher/user_fetcher.rb
|
92
93
|
- lib/qiita-export/image.rb
|
93
94
|
- lib/qiita-export/version.rb
|
94
95
|
- qiita-export.gemspec
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
require 'json'
|
3
|
-
require 'open-uri'
|
4
|
-
|
5
|
-
module QiitaExport::Fetcher
|
6
|
-
class UserFetcher < ApiFetcher
|
7
|
-
|
8
|
-
PER_PAGE = 100
|
9
|
-
|
10
|
-
def find_articles
|
11
|
-
articles = []
|
12
|
-
page = 1
|
13
|
-
while true
|
14
|
-
user_articles = find_user_articles(page)
|
15
|
-
break if user_articles.empty?
|
16
|
-
|
17
|
-
user_articles.each do |user_article|
|
18
|
-
articles << to_article(user_article)
|
19
|
-
end
|
20
|
-
|
21
|
-
page += 1
|
22
|
-
sleep(0.3)
|
23
|
-
end
|
24
|
-
articles.sort { |a, b| a.created_at <=> b.created_at }
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def find_user_articles(page)
|
30
|
-
open("https://#{api_domain}/api/v2/users/#{user_id}/items?page=#{page}&per_page=#{PER_PAGE}", request_header) do |io|
|
31
|
-
JSON.parse(io.read)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|