kuport 0.1.4 → 0.1.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6841261656c40a5000fc5833d9e523af4175fd0a
4
- data.tar.gz: 6acf47faf6733559a31ef6e5739f770eb9155456
3
+ metadata.gz: 9cfd6d6c849f5f34ca6037044bd3905953fc4499
4
+ data.tar.gz: 52db103a1eccf46388b60cb6d441472e642888e6
5
5
  SHA512:
6
- metadata.gz: d38df664332a587adcb785f1f2979bded64284cb6e86ef22cf7fb4647945749d201180490c3cd5be7e6a1d6391d945c9930125b0d78d8f3a8b9ef40088c3356d
7
- data.tar.gz: dafed4261b2058fc94ef504d7ff03d84f1faa6d5d17741bb8788113bac5e869b9c7681c5de5466a7009ff7de9b92079a1f3522690ac0ff061912ef1335a5bca4
6
+ metadata.gz: 2f6d15a9d1ec0b12d0a691b2c5394738c16e6f068db30b31ea8eecad3b4bc82aff628c766de5a792cf4689dcc651a8b95499003505f16cba8dec85f7d04a60dc
7
+ data.tar.gz: 35ab6aa99e4e4f7bc313135022528d8643ccc84dc29c2c98dded5a6d1dc9c1848e00948a2a61a4760814ce740873f50b87625f8267e8f4fdc8e35d6d52231341
data/README.md CHANGED
@@ -12,21 +12,7 @@ $ gem install kuport
12
12
 
13
13
  ### Command
14
14
 
15
- 端末でjsonを読むには`jid`がおすすめ。
16
-
17
- ```bash
18
- $ go get github.com/simeji/jid/cmd/jid
19
- $ cat sample.json | jid
20
- ```
21
-
22
- 決め打ちで処理するなら`jq`などを使用。
23
-
24
- 一度ログインすればキャッシュが効くので、暫くは`--id`とパスワード入力は不要。
25
-
26
- `--download`で複数のファイルを一括で落とすにはjqなどで上手くフィルタして`name`と`path`を含むディクショナリのリストを取り出す必要がある。
27
- `[{name: 'Name', path: 'https://~~'}, ...]`
28
-
29
- ```bash
15
+ ```bash
30
16
  # 個人宛メッセージ取得
31
17
  kuport --id jx91234 -m
32
18
 
@@ -39,12 +25,12 @@ kuport --id jx91234 -m read
39
25
  kuport --id jx91234
40
26
 
41
27
 
42
- # キューポートからファイルを1つダウンロード
43
- kuport --download URL --output-file FILE
28
+ # URLをダウンロードしてNAMEとして保存
29
+ kuport --download NAME:URL
44
30
 
45
31
 
46
- # メッセージの添付ファイルをまとめてダウンロード(jqでjsonパース)
47
- kuport --id jx91234 -m | jq '.[0].links' | kuport --download
32
+ # メッセージの添付ファイルをまとめてダウンロード
33
+ kuport --id jx91234 -m | kuport --download
48
34
 
49
35
 
50
36
  # 動的にダウンロードするファイルを選択
@@ -55,13 +41,31 @@ kuport --id jx91234 -m | jid | kuport --download
55
41
  kuport -t
56
42
 
57
43
 
58
- # 電子教材の特定の科目をダウンロード
59
- kuport --materials | jq 'map(select( .["subject"] | test("^線形代数") ).links | .[])' | kuport --download
44
+ # 電子教材から科目指定でダウンロード
45
+ kuport --materials | kuport --filter='subject:線形代数' | kuport --download
60
46
 
61
47
  ```
62
48
 
49
+ 一度ログインすればキャッシュが効くので、しばらくは`--id`とパスワード入力は不要。
50
+
51
+ `--download`はJSONから`name`と`path`を持つ辞書を再帰的に探索してダウロードできる。
52
+ `[{name: 'Name', path: 'https://~~'}, ...]`
53
+
54
+
55
+ 端末でjsonを読むには`jid`がおすすめ。
56
+
57
+ ```bash
58
+ $ go get github.com/simeji/jid/cmd/jid
59
+ $ cat sample.json | jid
60
+ ```
61
+
62
+ プロキシの設定は環境変数`HTTP_PROXY`, `HTTPS_PROXY`,`ALL_PROXY`から読み込む。
63
+ `--proxy`でも設定可能。
64
+
65
+
66
+
63
67
  ### Library
64
- ```ruby
68
+ ```ruby
65
69
  require 'kuport'
66
70
  kp = Kuport.new
67
71
  kp.login('jx91234')
@@ -80,12 +84,22 @@ puts timetable.to_json
80
84
 
81
85
  puts materials.to_json
82
86
 
83
- kp.download(url, name)
84
- kp.download([{name: 'File.pdf', path: 'https://example.com/file.pdf'}, ])
87
+ kp.download(name, url)
88
+ kp.download_with_json("[{name: 'File.pdf', path: 'https://example.com/file.pdf'}]")
85
89
 
86
90
  kp.cookies_clear
87
91
  ```
88
92
 
93
+ ## Configure file
94
+
95
+ ~/.kuportrc.json
96
+
97
+ ```json
98
+ {
99
+ "id": "jx91234"
100
+ }
101
+ ```
102
+
89
103
  ## Formats
90
104
 
91
105
  ### message
@@ -102,7 +116,7 @@ kp.cookies_clear
102
116
  },
103
117
  {
104
118
  "name": "画像.png",
105
- "path": "https://example.com/img/image1.pdf"
119
+ "path": "https://example.com/img/image1.png"
106
120
  }
107
121
  ]
108
122
  },
@@ -179,6 +193,16 @@ kp.cookies_clear
179
193
 
180
194
  ### materials
181
195
 
196
+ | キー | 値 |
197
+ |------------|----------------------------------|
198
+ | subject | String 科目名 |
199
+ | teacher | String 教員名 |
200
+ | title | String 資料タイトル |
201
+ | period | String 公開期間 |
202
+ | downloaded | Boolean ダウンロード状態 |
203
+ | links | [{name, path}, ...] ファイル一覧 |
204
+
205
+
182
206
  ```
183
207
  [
184
208
  {
@@ -186,7 +210,7 @@ kp.cookies_clear
186
210
  "teacher": "スゴイ先生",
187
211
  "title": "第100回目資料",
188
212
  "period": "2117/04/04 〜 2117/08/20",
189
- "state": "未ダウンロード",
213
+ "downloaded": true,
190
214
  "links": [
191
215
  {
192
216
  "name": "講義資料.pdf",
@@ -205,20 +229,12 @@ kp.cookies_clear
205
229
 
206
230
  ### download
207
231
 
208
- | 形式 | 説明 | 例 |
209
- |------------|---------------|------------------------------------------------------------------|
210
- | URL | ファイルのURL | "http://example.com/file.pdf" |
211
- | JSON | 単一の要素 | {"name": "file.pdf", "path": "http://example.com/abc.pdf"} |
212
- | JSON(配列) | 複数の要素 | [{"name": "img.png", "path": "http://example.com/efg.png"}, ...] |
213
-
214
-
215
- ## Contributing
216
-
217
- バグがあったらお気軽にどうぞ。
218
- コントリビューター募集中。
232
+ | 形式 | 説明 | 例 |
233
+ |----------|------------------------------|-----------------------------------------------------------|
234
+ | NAME:URL | URLをNAMEとして保存 | file.pdf:"http://example.com/file.pdf" |
235
+ | JSON | pathをnameとして保存(再帰的) | {"name": "abc.pdf", "path": "http://example.com/abc.pdf"} |
219
236
 
220
237
 
221
238
  ## License
222
239
 
223
240
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
224
-
data/bin/kuport CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'optparse'
3
3
  require 'kuport'
4
+ require 'json'
4
5
 
5
6
  using Kuport::ClassExtensions
6
7
 
@@ -9,32 +10,32 @@ example_usage = <<USAGE
9
10
  example usage
10
11
 
11
12
  # Get messages
12
- $ kuport --id jx91234 -m
13
+ kuport --id=jx91234 -m
13
14
 
14
15
 
15
16
  # Get already read messages
16
- $ kuport --id jx91234 -m read
17
+ kuport --id=jx91234 -m read
17
18
 
18
19
 
19
20
  # Login only(cache cookies)
20
- $ kuport --id jx91234
21
+ kuport --id=jx91234
21
22
 
22
23
 
23
- # Download file manually
24
- $ kuport --download URL --output-file FILE
24
+ # Download URL as NAME
25
+ kuport --download=NAME:URL
25
26
 
26
27
 
27
28
  # Download message attachment
28
- $ json="$(kuport --id jx91234 -m | jq '.[0].links')"
29
- $ kuport --download "$json"
29
+ json="$(kuport --id jx91234 -m | jq '.[0].links')"
30
+ kuport --download="$json"
30
31
 
31
32
 
32
33
  # Interactively download message attachment
33
- $ go get github.com/simeji/jid/cmd/jid
34
- $ kuport --download "$(kuport --id jx91234 -m | jid)"
34
+ go get github.com/simeji/jid/cmd/jid
35
+ kuport --download="$(kuport --id jx91234 -m | jid)"
35
36
 
36
37
  # Download specific subjects materials
37
- kuport --materials | jq 'map(select( .["subject"] | test("^Computer") ).links | .[])' | kuport --download
38
+ kuport --materials | kuport --filter='subject:Computer' | kuport --download
38
39
  USAGE
39
40
 
40
41
  def debug?
@@ -43,6 +44,17 @@ end
43
44
 
44
45
  require 'pry' if debug?
45
46
 
47
+ $kuport_human_readable = STDOUT.tty?
48
+ RC_FILE = File.expand_path('~/.kuportrc.json')
49
+
50
+ def putj(obj)
51
+ if $kuport_human_readable
52
+ puts JSON.pretty_generate(obj)
53
+ else
54
+ puts obj.to_json
55
+ end
56
+ end
57
+
46
58
  parser = OptionParser.new do |o|
47
59
  def o.options
48
60
  @options ||= {}
@@ -64,22 +76,23 @@ parser = OptionParser.new do |o|
64
76
  # sumarry_width=32, summary_indent=' '*4,
65
77
 
66
78
 
67
- o.on_setopt(:id, '-I', '--id ID', 'Student number')
68
- o.on_setopt(:download, '-D', '--download=[-|URL|JSON]',
79
+ o.on_setopt(:id, '-I', '--id=ID', 'Student number')
80
+ o.on_setopt(:filter, '-F', '--filter=KEY:PATTERN', 'Filter JSON contents')
81
+ o.on_setopt(:download, '-D', '--download=[-|NAME:URL|JSON]',
69
82
  'Download file.',
70
- 'URL need --output-file',
83
+ 'Download URL file as NAME',
71
84
  'JSON contain [{name: "FILE", path: "URL"}, ...]',
72
- "'-' read URL|JSON from stdin"){|v| v || '-'}
73
- o.on_setopt(:output_file, '-O', '--output-file FILE', 'Specify destination filename')
85
+ "'-' read NAME:URL or JSON from stdin"){|v| v || '-'}
74
86
  o.on_setopt(:clear_cookies, '-C', '--clear-cookies')
75
- o.on_setopt(:proxy, '-P', '--proxy SERVER:PORT')
87
+ o.on_setopt(:proxy, '-P', '--proxy=SERVER:PORT')
88
+ o.on_setopt(:human_readable,'-H', '--[no-]human-readable'){|v| $kuport_human_readable = v}
76
89
  o.separator('')
77
90
 
78
- o.on_select(:messages, '-m', '--messages [TYPE]', %i[default read backno],
91
+ o.on_select(:messages, '-m', '--messages=[TYPE]', %i[default read backno],
79
92
  "read\tAlready read messages",
80
93
  "backno\tBack number messages(Unimplemented)")
81
- o.on_select(:timetable, '-t', '--timetable [TYPE]', %i[default compact])
82
- o.on_select(:materials, '-d', '--materials [TYPE]', %i[default])
94
+ o.on_setopt(:materials, '-d', '--materials')
95
+ o.on_select(:timetable, '-t', '--timetable=[TYPE]', %i[default compact])
83
96
  o.separator('')
84
97
 
85
98
  o.separator('')
@@ -88,7 +101,14 @@ end
88
101
 
89
102
  ARGV << '--help' if ARGV.empty?
90
103
  parser.permute!(ARGV)
91
- opts= parser.options
104
+ opts = parser.options
105
+
106
+ # read config
107
+ config = {}
108
+ if File.readable?(RC_FILE)
109
+ config = JSON.parse(File.read(RC_FILE), {symbolize_names: true})
110
+ end
111
+ config.each{|k,v| opts[k] = config[k] unless opts.has_key?(k)}
92
112
 
93
113
  if debug?
94
114
  warn "opts #{opts}"
@@ -96,21 +116,34 @@ if debug?
96
116
  end
97
117
 
98
118
  # kp = KuportView.new
99
- kp = Kuport.new(proxy: opts[:proxy])
119
+ kp = Kuport.new(opts)
100
120
 
101
121
  if opts[:clear_cookies]
102
122
  kp.cookies_clear
103
123
  exit unless opts[:id]
104
124
  end
105
125
 
126
+ if opts[:filter]
127
+ key,pattern = opts[:filter].split(':', 2)
128
+ putj Kuport.filter(key, pattern)
129
+ exit
130
+ end
131
+
106
132
  if opts[:id]
107
133
  kp.login(opts[:id])
108
134
  end
109
135
 
110
136
  if opts[:download]
111
- Kuport.quit('Need --output-file', 20) if opts[:download].url? && opts[:output_file].nil?
112
137
  opts[:download] = STDIN.read if opts[:download] == '-'
113
- kp.download(opts[:download], opts[:output_file])
138
+
139
+ name,url = opts[:download].split(':', 2)
140
+ if url.url?
141
+ # NAME:URL
142
+ kp.download_file(name, url)
143
+ else
144
+ # JSON
145
+ kp.download_with_json(opts[:download])
146
+ end
114
147
  end
115
148
 
116
149
  # get data
@@ -128,20 +161,20 @@ if opts[:messages]
128
161
  kp.messages_backno
129
162
  end
130
163
 
131
- puts mes.to_json
164
+ putj mes
132
165
  end
133
166
 
134
167
  # timetable
135
168
  if opts[:timetable]
136
169
  table = kp.timetable
137
170
  table.compact if opts[:timetable] == :compact
138
- puts table.to_json
171
+ putj table
139
172
  end
140
173
 
141
174
  # materials
142
- if opts[:materials]
175
+ if opts.has_key?(:materials)
143
176
  mat = kp.materials
144
- puts mat.to_json
177
+ putj mat
145
178
  end
146
179
 
147
180
  if debug?
data/lib/kuport.rb CHANGED
@@ -33,12 +33,16 @@ class Kuport
33
33
  @@cookies_file = File.join(@@cache_dir, 'cookies.jar')
34
34
  FileUtils.mkdir_p(@@cache_dir)
35
35
 
36
- def initialize(proxy: nil)
36
+ def initialize(**opts)
37
37
  agent.html_parser = self.class
38
38
  cookies_load
39
39
 
40
- proxy ||= Kuport.get_proxy_env_var
41
- if proxy
40
+ # If proxy is blank, don't use proxy
41
+ proxy = opts.key?(:proxy) ? opts[:proxy] : Kuport.get_proxy_env_var
42
+
43
+ if proxy.blank?
44
+ Kuport.clear_proxy_env_var
45
+ else
42
46
  agent.set_proxy(*Kuport.parse_proxy_str(proxy))
43
47
  end
44
48
  end
@@ -133,26 +137,39 @@ class Kuport
133
137
  DownloadError.new(file_path)
134
138
  end
135
139
 
136
- # url_or_json is "http://....", {name:, path:}, or [{name:, path:}, ...]
137
- # If url_or_json is URL, need file_path
138
- def download(url_or_json, file_path=nil)
139
- if url_or_json.url?
140
- download_file(file_path, url_or_json)
141
- return
140
+ # json is {name:, path:} or [{name:, path:}, ...]
141
+ def download_with_json(json_str)
142
+ h = JSON.parse(json_str, {symbolize_names: true})
143
+ find_links(h).each do |h|
144
+ download_file(h[:name], h[:path])
145
+ puts h[:name]
142
146
  end
143
147
 
144
- json = JSON.parse(url_or_json, {symbolize_names: true})
145
- if Array === json
146
- json.each do |link|
147
- download_file(link[:name], link[:path])
148
- puts link[:name]
148
+ rescue JSON::ParserError
149
+ raise DownloadError.new("JSON parse error '#{json}'")
150
+ end
151
+
152
+ # Takeout pair of :name and ;path recursively
153
+ def find_links(j)
154
+ links = []
155
+
156
+ if j.is_a?(Array)
157
+ j.each{|v| links.push(*find_links(v))}
158
+ elsif j.is_a?(Hash)
159
+ link = j.take_with_keys(:name, :path)
160
+ links.push(link) if link
161
+
162
+ j.each do |_,v|
163
+ links.push(*find_links(v)) if v.is_a?(Array) || v.is_a?(Hash)
149
164
  end
150
- else
151
- download_file(json[:name], json[:path])
152
165
  end
153
166
 
154
- rescue JSON::ParserError
155
- raise DownloadError.new("JSON parse error '#{url_or_json}'")
167
+ return links
168
+ end
169
+
170
+ # return Hash
171
+ def self.filter(key, pattern)
172
+ JSON.load(STDIN.read).select{|m| m[key].to_s.match?(pattern)}
156
173
  end
157
174
 
158
175
  # html parser for Mechanize. force encode to UTF-8
data/lib/kuport/helper.rb CHANGED
@@ -52,7 +52,13 @@ class Kuport
52
52
  end
53
53
 
54
54
  def parse_proxy_str(str)
55
- str.split(':')[0..1]
55
+ str = 'http://' + str if str !~ /\A\w+:\/\//
56
+ u = URI.parse(str)
57
+ [u.host, u.port]
58
+ end
59
+
60
+ def clear_proxy_env_var
61
+ ENV.delete_if{|k,v| k =~ /_proxy/i }
56
62
  end
57
63
  end
58
64
 
@@ -77,6 +83,14 @@ class Kuport
77
83
  end
78
84
  end
79
85
 
86
+ refine Hash do
87
+ def take_with_keys(*keys)
88
+ ret = {}
89
+ keys.each{|k| ret[k] = self.delete(k) if self.key?(k)}
90
+ return ret.empty? ? nil : ret
91
+ end
92
+ end
93
+
80
94
  refine Nokogiri::XML::Node do
81
95
  def br_to_return
82
96
  self.search('br').each{|br| br.replace("\n")}
@@ -1,4 +1,3 @@
1
- require 'pry'
2
1
  class Kuport::Materials
3
2
  using Kuport::ClassExtensions
4
3
  attr_reader :trs, :base_url
@@ -19,7 +18,7 @@ class Kuport::Materials
19
18
  teacher: tds[2].text,
20
19
  title: tds[3].text,
21
20
  period: tds[4].text,
22
- state: tds[5].text,
21
+ downloaded: (tds[5].text == 'ダウンロード済み'),
23
22
  links: tds[6].css('li').map{|li| parse_link(li)},}.freeze
24
23
  end
25
24
 
@@ -83,7 +83,7 @@ class Kuport::Timetable
83
83
  @data_str = to_h.to_s
84
84
  end
85
85
 
86
- def to_json
87
- @data_json ||= to_h.to_json
86
+ def to_json(*a)
87
+ @data_json ||= to_h.to_json(*a)
88
88
  end
89
89
  end
@@ -1,3 +1,3 @@
1
1
  class Kuport
2
- VERSION = '0.1.4'
2
+ VERSION = '0.1.5'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kuport
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - u+
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-21 00:00:00.000000000 Z
11
+ date: 2017-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri