├── .gitignore
├── COPYING
├── README.md
├── check_in.py
├── choose_cs_exp.py
├── choose_pe_class.py
├── credentials.sample.py
├── export_physics_experiment.py
├── export_timetable.py
├── get_course_data.py
├── get_electricity_balance.py
├── get_grades.py
├── get_network_balance_of_current_device.py
├── get_network_usage.py
├── get_rs_campus_recruitment.py
├── get_sport_measure_score.py
├── get_sports_punch_records.py
├── get_xdoj_outside.py
└── get_xidian_news.py
/.gitignore:
--------------------------------------------------------------------------------
1 | configurations.py
2 | credentials.py
3 |
4 | # Byte-compiled / optimized / DLL files
5 | __pycache__/
6 | *.py[cod]
7 | *$py.class
8 |
9 | # C extensions
10 | *.so
11 |
12 | # PyInstaller
13 | # Usually these files are written by a python script from a template
14 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
15 | *.manifest
16 | *.spec
17 |
18 | # Installer logs
19 | pip-log.txt
20 | pip-delete-this-directory.txt
21 |
22 | # Unit test / coverage reports
23 | htmlcov/
24 | .tox/
25 | .coverage
26 | .coverage.*
27 | .cache
28 | nosetests.xml
29 | coverage.xml
30 | *.cover
31 | .hypothesis/
32 | .pytest_cache/
33 |
34 | # Translations
35 | *.mo
36 | *.pot
37 |
38 | # Django stuff:
39 | *.log
40 | local_settings.py
41 | db.sqlite3
42 |
43 | # Flask stuff:
44 | instance/
45 | .webassets-cache
46 |
47 | # Scrapy stuff:
48 | .scrapy
49 |
50 | # Sphinx documentation
51 | docs/_build/
52 |
53 | # PyBuilder
54 | target/
55 |
56 | # Jupyter Notebook
57 | .ipynb_checkpoints
58 |
59 | # pyenv
60 | .python-version
61 |
62 | # celery beat schedule file
63 | celerybeat-schedule
64 |
65 | # SageMath parsed files
66 | *.sage.py
67 |
68 | # Environments
69 | .env
70 | .venv
71 | env/
72 | venv/
73 | ENV/
74 | env.bak/
75 | venv.bak/
76 |
77 | # Spyder project settings
78 | .spyderproject
79 | .spyproject
80 |
81 | # Rope project settings
82 | .ropeproject
83 |
84 | # mkdocs documentation
85 | /site
86 |
87 | # mypy
88 | .mypy_cache/
89 |
90 | # ide
91 | .vscode/
92 | .idea/
93 |
94 | # res files
95 | .DS_Store
96 |
97 | test.py
98 | credentials.py
99 | configurations.py
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # xidian-scripts
2 |
3 | [](https://www.gnu.org/licenses/lgpl-3.0)
4 | [](https://www.python.org/)
5 |
6 | ## 这是什么?
7 |
8 | 西安电子科技大学校园生活的一些实用小脚本
9 |
10 | ## 开始使用
11 |
12 | 请在运行脚本前设置一些环境变量。Linux下可以写进`~/.*shrc`
13 |
14 | |环境变量|用到这个环境变量的脚本|补充说明|
15 | |:-:|:-:|:-:|
16 | |IDS_USER/IDS_PASS|export_timetable get_grades.py get_borrowed_books check_in get_course_data|对应西电统一认证服务的用户名密码|
17 | |WX_USER/WX_PASS|get_borrowed_books get_card_balance query_card_bill|由于此服务与统一认证密码保持一致,若脚本找不到这两个环境变量,则会使用IDS_USER/IDS_PASS|
18 | |PAY_USER/PAY_PASS|get_network_usage|对应zfw.xidian.edu.cn用户名密码,此脚本由于需要识别验证码,需要安装tesseract才能正常运行,且登陆速度可能较慢|
19 | |ENERGY_USER/ENERGY_PASS|get_electricity_balance|对应宿舍电费账户|
20 | |RS_USER/RS_PASS|get_rs_campus_recruitment|睿思校外站|
21 | |SPORTS_USER/SPORTS_PASS|get_sports_punch_records|对应体适能用户名和密码|
22 | |EXP_CS_PASSWORD|choose_cs_exp|计科院系统实验教学中心密码|
23 |
24 | ---
25 |
26 | 如果不想设置环境变量或者想一次性配好所有变量,可以通过编辑`credentials.py`完成:
27 |
28 | 1. 首先复制`credentials.sample.py`为`credentials.py`
29 | 2. 开始编辑`credentials.py`即可
30 |
31 | 注:`credentials.py`需要和你使用的脚本在同一个路径下
32 |
33 | ### For Example
34 |
35 | 在命令行直接运行:
36 | `IDS_USER=学号 IDS_PASS=密码 python3 get_grades.py`
37 |
38 | 或者在`~/.bashrc`(假如你使用的是bash)中加入:
39 | ```sh
40 | export IDS_USER=学号
41 | export IDS_PASS=密码
42 | ```
43 | 重启终端或执行`source ~/.bashrc`后执行:
44 | `python3 get_grades.py`
45 |
46 | ### Manifest
47 |
48 | * get_borrowed_books: 看看你借过哪些书
49 | * get_card_balance: 查询一卡通余额
50 | * get_electricity_balance*: 查询电量余额
51 | * get_grades: 看看你考了多少分
52 | * get_network_usage: 看看你的 10G 流量还有多少
53 | * get_xdoj_outside: 把你在 `acm.xidian.edu.cn` 上交过的代码都扒拉下来
54 | * export_timetable: 把当前学期课表保存为`.ics`格式,以便导入到日历软件中。
55 | * export_physics_experiment.py*: 将当前学期的物理实验保存为`.ics`格式,以便导入到日历软件中。
56 | * query_card_bill: 查询一卡通在指定时间段(30天内)的消费记录
57 | * get_rs_campus_recruitment: 获取睿思论坛上的校园招聘信息
58 | * check_in: 2020 晨午晚检
59 | * get_sports_punch_records: 查询体育打卡次数
60 | * choose_pe_class: 体育课选课
61 | * choose_cs_exp: 计科院实验选课
62 | * get_course_data:获取课程数据如签到次数,签到率等,保存为csv文件
63 | * get_network_balance_of_current_device*: 获取当前设备的校园网流量使用情况
64 |
65 | ### 备注
66 |
67 | 1. 标*号的脚本只能在西电内网使用
68 | 1. 设置好上面这些环境变量,就可以直接执行脚本了。你可以只保留或只下载自己所需要的脚本。
69 | 1. 如果希望将运行结果推送至类似[Server酱](https://sc.ftqq.com)这样的平台,可以参考下面的命令(以get_rs_campus_recruitment为例)
70 |
71 | ```bash
72 | echo "text=HR_news&desp=`python3 get_rs_campus_recruitment.py --markdown --urlencode`" | \
73 | curl -d @- https://sc.ftqq.com/{你的SEKEY}.send
74 | ```
75 |
76 | ## 参与贡献
77 |
78 | ### As a programmer
79 |
80 | 直接 PR 即可,同时我们欢迎其他自由的语言实现。
81 | 本仓库的目的更多是鼓励大家尝试在 GitHub 上参与程序的编写,请大胆提 Pull Request,不必担心。
82 | 仓库的维护者会尽最大可能帮助你熟悉 git workflow。
83 |
84 | ### As a reviewer
85 |
86 | 点击右上角的 watch,关注并检验每一次 PR 并对结果作出回复。
87 | 如何检验?使用 GNU diffutils 或你喜欢的工具应用 PR 邮件里的Patch Links。
88 |
89 | ### 要求
90 |
91 | 至少要保证能在 GNU/Linux 或者其他自由的操作系统下能运行。
92 | 只能在专有的操作系统上运行的不会允许(或者即使程序本身是自由的,但是依赖专有库的也不会允许)。
93 |
94 | ## 友情链接
95 |
96 | [Traintime PDA / XDYou]([https://www.coolapk.com/apk/249065](https://github.com/BenderBlog/traintime_pda)) by @BenderBlog
97 | [电表](https://www.coolapk.com/apk/249065) by @Robotxm
98 | [oh-my-xdu](https://github.com/zkonge/oh-my-xdu) by @zkonge
99 |
--------------------------------------------------------------------------------
/check_in.py:
--------------------------------------------------------------------------------
1 | import time
2 | import os
3 | import pytz
4 | import datetime
5 | import requests
6 |
7 | try:
8 | import credentials
9 | USERNAME = credentials.IDS_USERNAME
10 | PASSWORD = credentials.IDS_PASSWORD
11 | except ImportError:
12 | USERNAME, PASSWORD = [os.getenv(i) for i in ('IDS_USER', 'IDS_PASS')]
13 |
14 |
15 | def commit_data(username, password):
16 | sess = requests.session()
17 | sess.post(
18 | 'https://xxcapp.xidian.edu.cn/uc/wap/login/check', data={
19 | 'username': username,
20 | 'password': password
21 | })
22 | return sess.post(
23 | 'https://xxcapp.xidian.edu.cn/xisuncov/wap/open-report/save', data={
24 | 'sfzx': '1', 'tw': '1',
25 | 'area': '陕西省 西安市 长安区',
26 | 'city': '西安市', 'province': '陕西省',
27 | 'address': '陕西省西安市长安区兴隆街道梧桐大道西安电子科技大学长安校区',
28 | 'geo_api_info': '{"type":"complete","position":{"Q":34.129092068143,"R":108.83138888888902,"lng":108.831389,"lat":34.129092},"location_type":"html5","message":"Get geolocation success.Convert Success.Get address success.","accuracy":65,"isConverted":true,"status":1,"addressComponent":{"citycode":"029","adcode":"610116","businessAreas":[],"neighborhoodType":"","neighborhood":"","building":"","buildingType":"","street":"雷甘路","streetNumber":"266#","country":"中国","province":"陕西省","city":"西安市","district":"长安区","township":"兴隆街道"},"formattedAddress":"陕西省西安市长安区兴隆街道梧桐大道西安电子科技大学长安校区","roads":[],"crosses":[],"pois":[],"info":"SUCCESS"}',
29 | 'sfcyglq': '0', 'sfyzz': '0', 'qtqk': '', 'ymtys': '0'
30 | }
31 | ).json()['m']
32 |
33 |
34 | def get_hour_message():
35 | h = datetime.datetime.fromtimestamp(
36 | int(time.time()), pytz.timezone('Asia/Shanghai')).hour
37 | return "睡晨午晚"[h // 6]
38 |
39 |
40 | def main_handler(event, context):
41 | message = commit_data(USERNAME, PASSWORD)
42 | print(f'[{datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S")}] {message}')
43 | message = get_hour_message() + '检-' + message
44 |
45 | if __name__ == "__main__":
46 | main_handler(None, None)
47 |
--------------------------------------------------------------------------------
/choose_cs_exp.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2022 by the XiDian Open Source Community.
2 | #
3 | # This file is part of xidian-scripts.
4 | #
5 | # xidian-scripts is free software: you can redistribute it and/or modify it
6 | # under the terms of the GNU Lesser General Public License as published by the
7 | # Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # xidian-scripts is distributed in the hope that it will be useful, but WITHOUT
11 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with xidian-scripts. If not, see .
17 |
18 | # @author: https://github.com/akynazh
19 | # @date: 2023-03-09
20 |
21 | import asyncio
22 | import aiohttp
23 | import time
24 | import os
25 | from prettytable import PrettyTable
26 | from bs4 import BeautifulSoup
27 |
28 | try:
29 | import credentials
30 | USERNAME = credentials.IDS_USERNAME
31 | PASSWORD = credentials.EXP_CS_PASSWORD
32 | except ImportError:
33 | USERNAME, PASSWORD = [os.getenv(i) for i in ('IDS_USER', 'EXP_PASSWORD')]
34 | if not USERNAME or not PASSWORD:
35 | print('请设置环境变量 IDS_USER 和 EXP_PASSWORD')
36 | exit(1)
37 |
38 | BASE_URL = 'http://222.25.176.4'
39 | MAX_COROUINES = 5
40 | TIMEOUT = 3
41 | CLASS_NO = '2003%BC%B6'
42 |
43 |
44 | def DUMMY():
45 | return time.time() * 1000
46 |
47 |
48 | async def login(session: aiohttp.ClientSession):
49 | '''尝试登录
50 |
51 | :param aiohttp.ClientSession session
52 | :return bool: 登录成功与否
53 | '''
54 | resp = await session.post(
55 | url=f'{BASE_URL}/index.php',
56 | data={
57 | 'username': USERNAME,
58 | 'userpwd': PASSWORD,
59 | 'user': 'student',
60 | },
61 | )
62 | if resp.status != 200:
63 | return
64 | session.cookie_jar.update_cookies(resp.cookies)
65 | resp = await session.get(url=f'{BASE_URL}/student/default.php')
66 | if resp.status != 200:
67 | return
68 | resp_text = await resp.text()
69 | if resp_text.find(USERNAME) != -1:
70 | return True
71 |
72 |
73 | async def get_exp_info(session: aiohttp.ClientSession) -> dict:
74 | '''尝试获取实验信息:实验名称 => 实验对应编号 => 教室门牌号列表
75 |
76 | :param aiohttp.ClientSession session
77 | :return dict: 实验信息
78 | '''
79 | exp_info = []
80 |
81 | async def get_crnos_by_exp(name: str, cid: str):
82 | '''根据实验获取对应教室
83 |
84 | :param str name: 实验名称
85 | :param str cid: 实验编号
86 | '''
87 | if cid == '-1':
88 | return
89 | resp = await session.get(
90 | url=
91 | f'{BASE_URL}/student/ajax-showClassroom.php?dummy={DUMMY()}&cid={cid}&classno={CLASS_NO}',
92 | )
93 | if resp.status == 200:
94 | resp_text = await resp.text()
95 | crnos = resp_text.split('#')
96 | exp_info.append({
97 | 'cid': cid.strip(),
98 | 'name': name.strip(),
99 | 'crnos': crnos
100 | })
101 | else:
102 | exp_info.append({'cid': cid, 'name': name, 'crnos': []})
103 |
104 | resp = await session.get(
105 | url=
106 | f'{BASE_URL}/student/showCourses.php?dummy={DUMMY()}&classno={CLASS_NO}',
107 | )
108 | if resp.status != 200:
109 | return
110 | try:
111 | soup = BeautifulSoup(await resp.text(), 'lxml')
112 | options = soup.find(id='paikeFormId').find_all('option')
113 | tasks = [
114 | asyncio.ensure_future(
115 | get_crnos_by_exp(name=op.text, cid=op['value']))
116 | for op in options
117 | ]
118 | for task in asyncio.as_completed(tasks):
119 | await task
120 | return exp_info
121 | except Exception as e:
122 | print(e)
123 | return
124 |
125 |
126 | async def submit_exp_choice(session: aiohttp.ClientSession, crno: str,
127 | cid: str):
128 | '''尝试选实验
129 |
130 | :param aiohttp.ClientSession session
131 | :param str crno: 实验教室
132 | :param str cid: 实验编号
133 | :return bool: 是否成功(或需要修改参数)
134 | '''
135 | try:
136 | url = f'{BASE_URL}/student/ajax-submitXuanke.php?dummy={DUMMY()}&user={USERNAME}&crno={crno}&cid={cid}&classno={CLASS_NO}'
137 | # a sample: http://222.25.176.4/student/ajax-submitXuanke.php?dummy=1678160826939&user=20009100359&crno=E-II312&cid=115&classno=2003%BC%B6
138 | print(f'开始提交选择,请求地址:{url}')
139 | resp = await session.get(url=url)
140 | if resp.status == 200:
141 | code = await resp.text()
142 | code = code.strip()
143 | if code == '1':
144 | print('选课成功, 你可以在"查看已选课程"查看该课程信息')
145 | return True
146 | elif code == '2':
147 | print('你已经选过此课程了')
148 | return True
149 | elif code == '3':
150 | print('已经被选满')
151 | return True
152 | elif code == '4':
153 | print('提交过程出现错误')
154 | elif code == '5':
155 | print('在选择第 1 课次前,不能选择后面的课次')
156 | return True
157 | elif code == '6':
158 | print('你怎么可能点了不是第 1 次课的课程呢')
159 | return True
160 | elif code == '-1':
161 | print('该课程安排已经过了选课日期')
162 | return True
163 | else:
164 | print('出现错误,选课失败')
165 | else:
166 | print('出现错误,选课失败')
167 | except asyncio.CancelledError:
168 | pass
169 |
170 |
171 | async def get_submit_res(session):
172 | '''获取实验选择结果
173 | '''
174 | table = PrettyTable()
175 | url = f'{BASE_URL}/student/showMyCourses.php'
176 | print('尝试获取实验选择结果......')
177 | resp = await session.get(url)
178 | if resp.status == 200:
179 | try:
180 | soup = BeautifulSoup(await resp.text(), 'lxml')
181 | rows = soup.find('table').find_all('tr')
182 | for i, row in enumerate(rows):
183 | if i == 0:
184 | cols = row.find_all('th')
185 | table.field_names = [col.text.strip() for col in cols]
186 | else:
187 | cols = row.find_all('td')
188 | table.add_row([col.text.strip() for col in cols])
189 | print(table)
190 | except Exception as e:
191 | print(f'获取失败:{e}')
192 | else:
193 | print('获取失败,请重试')
194 |
195 |
196 | async def main():
197 | async with aiohttp.ClientSession() as session:
198 | print('尝试登录......')
199 | while True:
200 | if await login(session):
201 | print('登录成功!')
202 | break
203 | print('登录失败,请检查网络或用户名和密码')
204 | time.sleep(0.5)
205 | print(f'开启 {MAX_COROUINES} 个协程,尝试获取实验信息......')
206 | while True:
207 | info_flag = False
208 | tasks = [
209 | asyncio.ensure_future(get_exp_info(session))
210 | for i in range(MAX_COROUINES)
211 | ]
212 | for task in asyncio.as_completed(tasks):
213 | exp_info = await task
214 | if exp_info:
215 | info_flag = True
216 | break
217 | if info_flag:
218 | break
219 | print('成功获取实验信息:')
220 | for exp in exp_info:
221 | print(f'实验名称:{exp["name"]},实验编号:{exp["cid"]},实验教室:{exp["crnos"]}')
222 | # choose
223 | cid = input('请输入实验编号 >>> ')
224 | crno = input('请输入实验教室 >>> ')
225 | print(f'开启 {MAX_COROUINES} 个协程,尝试提交选择......')
226 | # submit choice
227 | while True:
228 | submit_flag = False
229 | tasks = [
230 | asyncio.create_task(
231 | submit_exp_choice(session=session, crno=crno, cid=cid))
232 | for _ in range(MAX_COROUINES)
233 | ]
234 | done, pending = await asyncio.wait(
235 | tasks, return_when=asyncio.FIRST_COMPLETED)
236 | for task in done:
237 | if task.result():
238 | submit_flag = True
239 | for task in pending:
240 | task.cancel()
241 | if submit_flag:
242 | break
243 | await get_submit_res(session)
244 |
245 |
246 | if __name__ == '__main__':
247 | asyncio.run(main())
--------------------------------------------------------------------------------
/choose_pe_class.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2022 by the XiDian Open Source Community.
2 | #
3 | # This file is part of xidian-scripts.
4 | #
5 | # xidian-scripts is free software: you can redistribute it and/or modify it
6 | # under the terms of the GNU Lesser General Public License as published by the
7 | # Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # xidian-scripts is distributed in the hope that it will be useful, but WITHOUT
11 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with xidian-scripts. If not, see .
17 |
18 | import pkg_resources
19 | import subprocess
20 | import sys
21 | import os
22 | try:
23 | pkg_resources.require(('libxduauth'))
24 | except (pkg_resources.DistributionNotFound, pkg_resources.VersionConflict):
25 | subprocess.check_call([
26 | sys.executable, '-m', 'pip', 'install', 'libxduauth'
27 | ])
28 |
29 | try:
30 | import credentials
31 | USERNAME = credentials.IDS_USERNAME
32 | PASSWORD = credentials.IDS_PASSWORD
33 | except ImportError:
34 | USERNAME, PASSWORD = [os.getenv(i) for i in ('IDS_USER', 'IDS_PASS')]
35 | if not USERNAME or not PASSWORD:
36 | print('请设置环境变量 IDS_USER 和 IDS_PASS')
37 | exit(1)
38 |
39 | import time
40 | from libxduauth import IDSSession
41 |
42 |
43 | def process():
44 | whatever = IDSSession("http://tybjxgl.xidian.edu.cn", USERNAME, PASSWORD)
45 | classes = whatever.post(
46 | "http://tybjxgl.xidian.edu.cn/admin/"
47 | "chooseCurriculum/showTeachingCurriculum"
48 | ).json()["data"]
49 | for i in classes:
50 | print(
51 | f'{str(i["id"])} {i["sysUserName"]} '
52 | f'{i["teachingCurriculumName"]} {i["teachingSchoolTimeName"]}'
53 | )
54 | ohyeah = input("输入你想上课程的id: ")
55 | choice = whatever.post(
56 | "http://tybjxgl.xidian.edu.cn/admin//"
57 | "stuTeacherCurriculum/chooseTeachingCurriculum?"
58 | f"teaCurriculumid={ohyeah}&_={int(round(time.time() * 1000))}"
59 | )
60 | print(choice.content.decode())
61 |
62 |
63 | if __name__ == "__main__":
64 | process()
65 |
--------------------------------------------------------------------------------
/credentials.sample.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2022 by the XiDian Open Source Community.
2 | #
3 | # This file is part of xidian-scripts.
4 | #
5 | # xidian-scripts is free software: you can redistribute it and/or modify it
6 | # under the terms of the GNU Lesser General Public License as published by the
7 | # Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # xidian-scripts is distributed in the hope that it will be useful, but WITHOUT
11 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with xidian-scripts. If not, see .
17 |
18 | STUDENT_ID = ''
19 | # 你的学号
20 |
21 | IDS_USERNAME = STUDENT_ID
22 | # ids.xidian.edu.cn的用户名,一般来说是学号
23 |
24 | IDS_PASSWORD = ''
25 | # ids.xidian.edu.cn的密码,一般是身份证后六位
26 |
27 | WX_USERNAME = STUDENT_ID
28 | # wx.xidian.edu.cn/wx_xdu的用户名
29 |
30 | WX_PASSWORD = IDS_PASSWORD
31 | # wx.xidian.edu.cn/wx_xdu的密码,和ids同步
32 | # 在ids上改密码这边的也会变,所以不要单独改
33 |
34 | XDOJ_USERNAME = STUDENT_ID
35 | # 202.117.120.31/xdoj的用户名
36 |
37 | XDOJ_PASSWORD = ''
38 | # 202.117.120.31/xdoj的密码
39 |
40 | PAY_USERNAME = STUDENT_ID
41 | # pay.xidian.edu.cn
42 |
43 | PAY_PASSWORD = ''
44 |
45 | PHYSICS_USERNAME = STUDENT_ID
46 | # Username for physics experiment system(wlsy.xidian.edu.cn). Normally it is your student id.
47 |
48 | PHYSICS_PASSWORD = ''
49 | # Password for physics experiment system
50 |
51 | ELECTRICITY_USERNAME = ''
52 | # Username for electricty system(http://10.168.55.50:8088/).
53 | # 查询工具: https://github.com/Hoooxz/xd-charge
54 |
55 | ELECTRICITY_PASSWORD = '123456'
56 | # Password for electricty system. Default value is 123456
57 |
58 | SPORTS_USERNAME = IDS_USERNAME
59 | # Username for sports system. Normally it is your student id.
60 |
61 | SPORTS_PASSWORD = ''
62 | # Password for sports system.
63 |
64 | RS_USERNAME = ''
65 | # Username for rs
66 |
67 | RS_PASSWORD = ''
68 | # Password for rs
69 |
70 | EXP_CS_PASSWORD = ''
71 | # Password for 222.25.176.4
--------------------------------------------------------------------------------
/export_physics_experiment.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2022 by the XiDian Open Source Community.
2 | #
3 | # This file is part of xidian-scripts.
4 | #
5 | # xidian-scripts is free software: you can redistribute it and/or modify it
6 | # under the terms of the GNU Lesser General Public License as published by the
7 | # Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # xidian-scripts is distributed in the hope that it will be useful, but WITHOUT
11 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with xidian-scripts. If not, see .
17 |
18 | import pkg_resources
19 | import subprocess
20 | import sys
21 | import os
22 | try:
23 | pkg_resources.require(('libxduauth', 'icalendar'))
24 | except (pkg_resources.DistributionNotFound, pkg_resources.VersionConflict):
25 | subprocess.check_call([
26 | sys.executable, '-m', 'pip', 'install', 'libxduauth', 'icalendar'
27 | ])
28 |
29 | try:
30 | import credentials
31 | USERNAME = credentials.PHYSICS_USERNAME
32 | PASSWORD = credentials.PHYSICS_PASSWORD
33 | except ImportError:
34 | USERNAME, PASSWORD = [os.getenv(i) for i in ('PHYSICS_USER', 'PHYSICS_PASS')]
35 | if not USERNAME or not PASSWORD:
36 | print('请设置环境变量 PHYSICS_USER 和 PHYSICS_PASS')
37 | exit(1)
38 |
39 | from icalendar import Calendar, Event
40 | from datetime import datetime, timedelta
41 | import requests
42 | import re
43 |
44 | expList = []
45 |
46 |
47 | def get_experiments():
48 | expList = []
49 | ses = requests.session()
50 | ses.post('http://wlsy.xidian.edu.cn/PhyEws/default.aspx',
51 | data={
52 | '__EVENTTARGET': '',
53 | '__EVENTARGUMENT': '',
54 | '__VIEWSTATE': '/wEPDwUKMTEzNzM0MjM0OWQYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgEFD2xvZ2luMSRidG5Mb2dpbutGpJNAAaBhxseXkh1n/woLBppW',
55 | '__VIEWSTATEGENERATOR': 'EE008CD9',
56 | '__EVENTVALIDATION': '/wEWBwLsvJu+AgKckJOGDgKD8YXRCQLJ5dDDBAKVx8n1CQKytMi0AQKcg465CqDdcB40IuBzviNuzXl4xNRdD759',
57 | 'login1$StuLoginID': USERNAME,
58 | 'login1$StuPassword': PASSWORD,
59 | 'login1$UserRole': 'Student',
60 | 'login1$btnLogin.x': '0',
61 | 'login1$btnLogin.y': '0'
62 | })
63 | html = ses.get('http://wlsy.xidian.edu.cn/PhyEws/student/select.aspx')
64 |
65 | pattern = re.compile(
66 | r'