kuport 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
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