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 +4 -4
- data/README.md +54 -38
- data/bin/kuport +60 -27
- data/lib/kuport.rb +35 -18
- data/lib/kuport/helper.rb +15 -1
- data/lib/kuport/materials.rb +1 -2
- data/lib/kuport/timetable.rb +2 -2
- data/lib/kuport/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9cfd6d6c849f5f34ca6037044bd3905953fc4499
|
4
|
+
data.tar.gz: 52db103a1eccf46388b60cb6d441472e642888e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
#
|
43
|
-
kuport --download URL
|
28
|
+
# URLをダウンロードしてNAMEとして保存
|
29
|
+
kuport --download NAME:URL
|
44
30
|
|
45
31
|
|
46
|
-
# メッセージの添付ファイルをまとめてダウンロード
|
47
|
-
kuport --id jx91234 -m |
|
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 |
|
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(
|
84
|
-
kp.
|
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.
|
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
|
-
"
|
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
|
211
|
-
| JSON
|
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
|
-
|
13
|
+
kuport --id=jx91234 -m
|
13
14
|
|
14
15
|
|
15
16
|
# Get already read messages
|
16
|
-
|
17
|
+
kuport --id=jx91234 -m read
|
17
18
|
|
18
19
|
|
19
20
|
# Login only(cache cookies)
|
20
|
-
|
21
|
+
kuport --id=jx91234
|
21
22
|
|
22
23
|
|
23
|
-
# Download
|
24
|
-
|
24
|
+
# Download URL as NAME
|
25
|
+
kuport --download=NAME:URL
|
25
26
|
|
26
27
|
|
27
28
|
# Download message attachment
|
28
|
-
|
29
|
-
|
29
|
+
json="$(kuport --id jx91234 -m | jq '.[0].links')"
|
30
|
+
kuport --download="$json"
|
30
31
|
|
31
32
|
|
32
33
|
# Interactively download message attachment
|
33
|
-
|
34
|
-
|
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 |
|
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
|
68
|
-
o.on_setopt(:
|
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
|
83
|
+
'Download URL file as NAME',
|
71
84
|
'JSON contain [{name: "FILE", path: "URL"}, ...]',
|
72
|
-
"'-' read URL
|
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
|
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
|
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.
|
82
|
-
o.on_select(:
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
171
|
+
putj table
|
139
172
|
end
|
140
173
|
|
141
174
|
# materials
|
142
|
-
if opts
|
175
|
+
if opts.has_key?(:materials)
|
143
176
|
mat = kp.materials
|
144
|
-
|
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(
|
36
|
+
def initialize(**opts)
|
37
37
|
agent.html_parser = self.class
|
38
38
|
cookies_load
|
39
39
|
|
40
|
-
proxy
|
41
|
-
|
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
|
-
#
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
download_file(
|
141
|
-
|
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
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
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
|
-
|
155
|
-
|
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
|
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")}
|
data/lib/kuport/materials.rb
CHANGED
@@ -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
|
-
|
21
|
+
downloaded: (tds[5].text == 'ダウンロード済み'),
|
23
22
|
links: tds[6].css('li').map{|li| parse_link(li)},}.freeze
|
24
23
|
end
|
25
24
|
|
data/lib/kuport/timetable.rb
CHANGED
data/lib/kuport/version.rb
CHANGED
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
|
+
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-
|
11
|
+
date: 2017-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|