arb-xmu-course 1.0.0
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 +7 -0
- data/.gitignore +11 -0
- data/.rake_tasks~ +6 -0
- data/Gemfile +9 -0
- data/README.md +36 -0
- data/Rakefile +2 -0
- data/arb-xmu-course.gemspec +23 -0
- data/bin/arb-xmu-course +236 -0
- data/bin/check_code.jpeg +0 -0
- data/lib/arb/xmu/course/models/course_entity.rb +35 -0
- data/lib/arb/xmu/course/models/course_schedule.rb +8 -0
- data/lib/arb/xmu/course/util/simple_des.rb +32 -0
- data/lib/arb/xmu/course/version.rb +7 -0
- data/lib/arb/xmu/course.rb +5 -0
- metadata +85 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 033892d7b5333bf00107dbfec09930a09e51d68d
|
4
|
+
data.tar.gz: 6ab649181d6263af37af3248b21084e679b8a28c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bef7169c325840623e5af693600a9b694614dc54791185647a343d08bd761290e2e8f1949e705976821b2389028de7320a7e5ebb091bbe7eca7e73f3302b2ade
|
7
|
+
data.tar.gz: 0a02725936ec1a99a09fff4ca0b61704cd1a97309c482a875ffe9075025ff3df7f6ecf6c095665673c34442cf68fa82d5e05eb6091d0db5fc167d906830d8557
|
data/.gitignore
ADDED
data/.rake_tasks~
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Arb::Xmu::Course
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/arb/xmu/course`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'arb-xmu-course'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install arb-xmu-course
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/arb-xmu-course.
|
36
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'arb/xmu/course/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "arb-xmu-course"
|
8
|
+
spec.version = Arb::Xmu::Course::VERSION
|
9
|
+
spec.authors = ["arybin"]
|
10
|
+
spec.email = ["arybin@163.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{XMU Course}
|
13
|
+
spec.description = %q{XMU Course}
|
14
|
+
spec.homepage = 'https://github.com/arybin-cn/arb-xmu-course'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "bin"
|
18
|
+
spec.executables = 'arb-xmu-course'
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
end
|
data/bin/arb-xmu-course
ADDED
@@ -0,0 +1,236 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'slop'
|
3
|
+
require 'json'
|
4
|
+
require 'httpclient'
|
5
|
+
require 'nokogiri'
|
6
|
+
require 'terminal-table'
|
7
|
+
require 'arb/xmu/course'
|
8
|
+
|
9
|
+
include Arb::Util
|
10
|
+
include Arb::Xmu::Course
|
11
|
+
|
12
|
+
TOKEN_FILE_NAME = 'encrypted_token'
|
13
|
+
TOKEN_SEPARATOR = ':'
|
14
|
+
|
15
|
+
|
16
|
+
def filter_text(raw)
|
17
|
+
if Enumerable===raw
|
18
|
+
return [].tap do |arr|
|
19
|
+
raw.each do |item|
|
20
|
+
arr<<filter_text(item)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
black_list =([] << "\r" << "\n" << "\t" << "'")
|
25
|
+
black_list.each do |tmp|
|
26
|
+
raw.gsub! tmp, ''
|
27
|
+
end
|
28
|
+
raw
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_up_account
|
32
|
+
$stdout.puts '请输入学号:'
|
33
|
+
stu_id= $stdin.gets.chomp
|
34
|
+
$stdout.puts '请输入密码:'
|
35
|
+
passwd= $stdin.gets.chomp
|
36
|
+
File.open TOKEN_FILE_NAME, 'w' do |file|
|
37
|
+
file.write (SimpleDes.encrypt(stu_id)+TOKEN_SEPARATOR+SimpleDes.encrypt(passwd))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def retrieve_check_code(client)
|
42
|
+
File.open 'check_code.jpeg', 'wb' do |file|
|
43
|
+
file.write(client.get('http://bkxk.xmu.edu.cn/xsxk/getCheckCode').body)
|
44
|
+
end
|
45
|
+
$stdout.puts '验证码图片已在当前目录生成,请查看后输入:'
|
46
|
+
$stdin.gets.chomp
|
47
|
+
end
|
48
|
+
|
49
|
+
def authorize_session(client, username, password)
|
50
|
+
checkCode = retrieve_check_code(client)
|
51
|
+
client.get 'http://bkxk.xmu.edu.cn/xsxk/login.html', username: username, password: password, checkCode: checkCode
|
52
|
+
#握手选课系统
|
53
|
+
client.get 'http://bkxk.xmu.edu.cn/xsxk/localInfo.html'
|
54
|
+
client.get 'http://bkxk.xmu.edu.cn/xsxk/index.html'
|
55
|
+
end
|
56
|
+
|
57
|
+
#获取选课轮次
|
58
|
+
def get_select_round(client, id)
|
59
|
+
round_id=nil
|
60
|
+
client.get('http://bkxk.xmu.edu.cn/xsxk/index.html').body.scan /addXklcList\((.*?)\)/m do |match|
|
61
|
+
tmpArr = filter_text(match[0].split(','))
|
62
|
+
if tmpArr[2]==id.to_s
|
63
|
+
round_id=tmpArr[1]
|
64
|
+
break
|
65
|
+
end
|
66
|
+
end
|
67
|
+
round_id
|
68
|
+
end
|
69
|
+
|
70
|
+
#获取主修选课轮次
|
71
|
+
def get_main_select_round(client)
|
72
|
+
get_select_round(client, 1)
|
73
|
+
end
|
74
|
+
|
75
|
+
def show_courses_in_table(courses)
|
76
|
+
table = Terminal::Table.new do |table|
|
77
|
+
table.add_row %w{ID 课程名称 学分 班号 主讲老师 总学时}
|
78
|
+
courses.each do |course_entity|
|
79
|
+
table.add_separator
|
80
|
+
table.add_row course_entity.to_a
|
81
|
+
end
|
82
|
+
end
|
83
|
+
$stdout.puts table
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_courses(raw_html)
|
87
|
+
|
88
|
+
course_entities = []
|
89
|
+
count=0
|
90
|
+
raw_html.scan /top\.createJxbObj\((.*?)\)/m do |match|
|
91
|
+
tmpArr = filter_text(match[0].split(','))
|
92
|
+
course_entities << CourseEntity.new do |entity|
|
93
|
+
entity.index= (count=count+1)
|
94
|
+
entity.id= tmpArr[1]
|
95
|
+
entity.name= tmpArr[4]
|
96
|
+
entity.credit= tmpArr[10]
|
97
|
+
entity.teacher= tmpArr[14]
|
98
|
+
entity.period= tmpArr[8]
|
99
|
+
entity.class_name= tmpArr[5]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
course_entities
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def request_select_course(client, course_entity, xxlx, lcid)
|
107
|
+
msg = client.get 'http://bkxk.xmu.edu.cn/xsxk/elect.html',
|
108
|
+
method: 'handleZxxk',
|
109
|
+
jxbid: course_entity.id,
|
110
|
+
xxlx: xxlx,
|
111
|
+
xklc: lcid
|
112
|
+
JSON::parse msg.body
|
113
|
+
end
|
114
|
+
|
115
|
+
def create_attempt_thread(max_interval, client, course_entity, xxlx, lcid)
|
116
|
+
Thread.new do
|
117
|
+
count=0
|
118
|
+
loop do
|
119
|
+
count+=1
|
120
|
+
interval = 1+rand(max_interval)
|
121
|
+
sleep interval
|
122
|
+
res = request_select_course(client, course_entity, xxlx, lcid)
|
123
|
+
if res[:success]
|
124
|
+
$stdout.puts "课程:《#{course_entity.name}》已经成功选课!"
|
125
|
+
break
|
126
|
+
else
|
127
|
+
$stdout.puts "课程:《#{course_entity.name}》第#{count}次尝试选课失败,#{interval}秒后将重试。"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
def select_school_elective(client, username, password)
|
136
|
+
authorize_session(client, username, password)
|
137
|
+
lcid=get_main_select_round(client)
|
138
|
+
|
139
|
+
school_courses = parse_courses((client.get 'http://bkxk.xmu.edu.cn/xsxk/yxxx.html').body)
|
140
|
+
show_courses_in_table school_courses
|
141
|
+
|
142
|
+
$stdout.puts
|
143
|
+
$stdout.puts '输入要选的课程ID, 以空格分割:'
|
144
|
+
|
145
|
+
ids = $stdin.gets.chomp.split(' ')
|
146
|
+
|
147
|
+
$stdout.puts '输入最大重试间隔时间,默认3秒,要求不得低于2秒:'
|
148
|
+
|
149
|
+
max_interval = $stdin.gets.chomp.to_i
|
150
|
+
max_interval = 2 if max_interval<2
|
151
|
+
|
152
|
+
ids.each do |id|
|
153
|
+
create_attempt_thread(max_interval, client, school_courses.find { |course| course.index==id.to_i }, 1, lcid)
|
154
|
+
end
|
155
|
+
|
156
|
+
loop do
|
157
|
+
sleep 3
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
def select_general_elective
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
def select_public
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
unless (File.exists? TOKEN_FILE_NAME)
|
173
|
+
puts '请先设置账户信息(账户信息会先加密然后保存在本地,用于授权选课系统)'
|
174
|
+
set_up_account
|
175
|
+
exit
|
176
|
+
end
|
177
|
+
|
178
|
+
stu_id, passwd=nil
|
179
|
+
client = HTTPClient.new
|
180
|
+
|
181
|
+
File.open TOKEN_FILE_NAME, 'r' do |file|
|
182
|
+
stu_id, passwd=SimpleDes.decrypt(file.read.split(TOKEN_SEPARATOR))
|
183
|
+
end
|
184
|
+
|
185
|
+
opts = Slop.parse do |o|
|
186
|
+
o.bool *%w{-h --help}, '显示帮助'
|
187
|
+
o.bool *%w{-c --clear}, '清除本地账户信息'
|
188
|
+
o.bool *%w{-r --reset}, '重置账户信息'
|
189
|
+
|
190
|
+
#院选课程 xxlx=4
|
191
|
+
o.bool *%w{-s --school}, '院选选课'
|
192
|
+
#校选课程 xxlx=3
|
193
|
+
o.bool *%w{-g --general}, '校选选课'
|
194
|
+
#公共课程 xxlx=5
|
195
|
+
o.bool *%w{-p --public}, '公共课选课'
|
196
|
+
end
|
197
|
+
|
198
|
+
case true
|
199
|
+
when opts.help?
|
200
|
+
puts(opts) && exit
|
201
|
+
when opts.clear?
|
202
|
+
File.delete(TOKEN_FILE_NAME) && exit
|
203
|
+
when opts.reset?
|
204
|
+
set_up_account && exit
|
205
|
+
when opts.school?
|
206
|
+
select_school_elective(client, stu_id, passwd)
|
207
|
+
when opts.general?
|
208
|
+
# select_general_elective
|
209
|
+
when opts.public?
|
210
|
+
# select_public
|
211
|
+
end
|
212
|
+
|
213
|
+
# client = HTTPClient.new
|
214
|
+
|
215
|
+
# #session init
|
216
|
+
# client.get 'http://bkxk.xmu.edu.cn/xsxk/login.html'
|
217
|
+
#
|
218
|
+
# File.open 'checkcode.jpeg','wb' do |file|
|
219
|
+
# file.write(client.get('http://bkxk.xmu.edu.cn/xsxk/getCheckCode').body)
|
220
|
+
# end
|
221
|
+
#
|
222
|
+
# puts 'enter your student id'
|
223
|
+
# user= gets.chomp
|
224
|
+
# puts 'enter your password'
|
225
|
+
# passwd=gets.chomp
|
226
|
+
# puts 'enter the checkcode'
|
227
|
+
# checkcode=gets.chomp
|
228
|
+
#
|
229
|
+
# client.get 'http://bkxk.xmu.edu.cn/xsxk/login.html',username: user,password: passwd,checkCode: checkcode
|
230
|
+
#
|
231
|
+
# puts (client.get 'http://bkxk.xmu.edu.cn/xsxk/localInfo.html').body
|
232
|
+
#
|
233
|
+
# Nokogiri::parse((client.get 'http://bkxk.xmu.edu.cn/xsxk/index.html').body).css('script').each do |x|
|
234
|
+
# puts x.text
|
235
|
+
# end
|
236
|
+
#
|
data/bin/check_code.jpeg
ADDED
Binary file
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Arb
|
2
|
+
module Xmu
|
3
|
+
module Course
|
4
|
+
class CourseEntity
|
5
|
+
#选课系统课程标识
|
6
|
+
attr_accessor :id
|
7
|
+
#索引
|
8
|
+
attr_accessor :index
|
9
|
+
#课程名
|
10
|
+
attr_accessor :name
|
11
|
+
#学分
|
12
|
+
attr_accessor :credit
|
13
|
+
#教师名
|
14
|
+
attr_accessor :teacher
|
15
|
+
#班级
|
16
|
+
attr_accessor :class_name
|
17
|
+
#总学时
|
18
|
+
attr_accessor :period
|
19
|
+
|
20
|
+
#Entity.new(index: 1,credit: 3, ...)
|
21
|
+
def initialize(**hash_args)
|
22
|
+
yield self if block_given?
|
23
|
+
hash_args.keys.each do |key|
|
24
|
+
send "#{key}=", hash_args[key]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
#for row output
|
29
|
+
def to_a
|
30
|
+
[index, name, credit, class_name, teacher, period]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
module Arb
|
5
|
+
module Util
|
6
|
+
class SimpleDes
|
7
|
+
ALG = 'DES-EDE3-CBC'
|
8
|
+
KEY = (Dir.pwd.split('').select { |char| char=~/\w/ }.join+'bYaRyBin')[0..7]
|
9
|
+
DES_KEY = KEY.swapcase
|
10
|
+
class << self
|
11
|
+
%i{encrypt decrypt}.each do |type|
|
12
|
+
define_method type do |input|
|
13
|
+
if Enumerable===input
|
14
|
+
return [].tap do |arr|
|
15
|
+
input.each do |item|
|
16
|
+
arr<<(send type, item)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
des = OpenSSL::Cipher::Cipher.new(ALG)
|
21
|
+
des.pkcs5_keyivgen(KEY, DES_KEY)
|
22
|
+
des.send type
|
23
|
+
input=Base64.decode64(input) if :decrypt==type
|
24
|
+
res =(des.update(input)<<des.final)
|
25
|
+
return Base64.encode64(res).chomp if :encrypt==type
|
26
|
+
res
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: arb-xmu-course
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- arybin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-07-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: XMU Course
|
42
|
+
email:
|
43
|
+
- arybin@163.com
|
44
|
+
executables:
|
45
|
+
- arb-xmu-course
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- ".gitignore"
|
50
|
+
- ".rake_tasks~"
|
51
|
+
- Gemfile
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- arb-xmu-course.gemspec
|
55
|
+
- bin/arb-xmu-course
|
56
|
+
- bin/check_code.jpeg
|
57
|
+
- lib/arb/xmu/course.rb
|
58
|
+
- lib/arb/xmu/course/models/course_entity.rb
|
59
|
+
- lib/arb/xmu/course/models/course_schedule.rb
|
60
|
+
- lib/arb/xmu/course/util/simple_des.rb
|
61
|
+
- lib/arb/xmu/course/version.rb
|
62
|
+
homepage: https://github.com/arybin-cn/arb-xmu-course
|
63
|
+
licenses: []
|
64
|
+
metadata: {}
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 2.4.8
|
82
|
+
signing_key:
|
83
|
+
specification_version: 4
|
84
|
+
summary: XMU Course
|
85
|
+
test_files: []
|