qiita-export 0.0.1 → 0.0.2
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 +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
|