├── .github
└── workflows
│ └── sync.yml
├── .gitignore
├── LICENSE
├── README.md
├── bath
├── go
│ ├── README.md
│ ├── main.go
│ └── tokens.txt
└── python
│ ├── README.md
│ └── bath.py
├── check
├── README.md
├── check.crontab.bash
├── check.py
└── users.txt
├── crontab.bash
├── leave
├── README.md
├── index.html
├── leave.crontab.bash
├── leave.py
└── users.txt
└── requirements.txt
/.github/workflows/sync.yml:
--------------------------------------------------------------------------------
1 | name: Sync to Gitee
2 | on:
3 | push:
4 | branches:
5 | - master
6 | jobs:
7 | sync:
8 | name: Sync to Gitee
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Sync to Gitee
12 | uses: wearerequired/git-mirror-action@master
13 | env:
14 | SSH_PRIVATE_KEY: ${{ secrets.GITEE_PRIVATE_KEY }}
15 | with:
16 | source-repo: "git@github.com:OhYee/bupt-scripts.git"
17 | destination-repo: "git@gitee.com:OhYee/bupt-scripts.git"
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 OhYee
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 北邮脚本汇总
2 |
3 | [](https://gitee.com/OhYee/bupt-scripts)
4 |
5 | 各种可能用得到的脚本,由于大部分每天都要点,尽管都不需要抢,但是很麻烦,所以用脚本实现自动化。
6 |
7 | 各脚本的解释见对应的 README
8 |
9 | - [浴室预约 (Python 版)](./bath/python)
10 | - [浴室预约 (Go 版)](./bath/go)
11 | - [疫情防控通打卡](./check)
12 | - [临时出入校申请](./leave)
--------------------------------------------------------------------------------
/bath/go/README.md:
--------------------------------------------------------------------------------
1 | # Go 语言版浴室预约脚本
2 |
3 | 该版本是为了编译出可以在路由器运行的自动预约程序而写的
4 |
5 | Go 交叉编译见 [将 Go 程序编译至 OpenWRT](https://www.oyohyee.com/post/note_compile_go_to_openwrt)
6 |
7 | ## 使用
8 |
9 | ```
10 | -d 调试模式
11 | -debug
12 | 调试模式
13 | -s 预约模式
14 | -submit
15 | 预约模式
16 | -t string
17 | Token 文件路径
18 | -tokens string
19 | Token 文件路径
20 | ```
21 |
22 | 使用`-t`指定存储用户信息的文件,一行一个,内容为对应用户在预约系统的 cookies 字段
23 |
24 | 默认运行为保持 Token 模式,程序会按顺序访问对应页面,保持 Token 有效(建议每小时运行一次)**目前该保活机制已失效**
25 |
26 | 添加`-s`参数,使用预约模式。默认会预约次日 21:00:00 浴室 2 楼
--------------------------------------------------------------------------------
/bath/go/main.go:
--------------------------------------------------------------------------------
1 | //go:generate bash -c "GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -o bupt_bath"
2 |
3 | package main
4 |
5 | import (
6 | "flag"
7 | "fmt"
8 | "io/ioutil"
9 | "net/http"
10 | "net/url"
11 | "regexp"
12 | "strings"
13 | "time"
14 | )
15 |
16 | const (
17 | UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1301.400 QQBrowser/9.0.2524.400 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2875.116 Safari/537.36 NetType/WIFI MicroMessenger/7.0.5 WindowsWechat"
18 | ContentType = "application/x-www-form-urlencoded"
19 | )
20 |
21 | var (
22 | idReg, _ = regexp.Compile("
学工号: (\\d+)
")
23 | infoReg, _ = regexp.Compile("(.*)
")
24 | DEBUG = false
25 | )
26 |
27 | // Get 请求到指定链接
28 | func Get(url string, userAgent string, cookie string) (status int, body []byte, err error) {
29 | client := http.Client{}
30 | req, err := http.NewRequest("GET", url, nil)
31 | if err != nil {
32 | return
33 | }
34 |
35 | req.Header.Set("User-Agent", userAgent)
36 | req.Header.Set("Cookie", cookie)
37 |
38 | resp, err := client.Do(req)
39 | if err != nil {
40 | return
41 | }
42 | defer resp.Body.Close()
43 | status = resp.StatusCode
44 | body, err = ioutil.ReadAll(resp.Body)
45 | if err != nil {
46 | return
47 | }
48 | return
49 | }
50 |
51 | // Post 请求到指定链接
52 | func Post(url string, data url.Values, userAgent string, cookie string) (status int, body []byte, err error) {
53 | client := http.Client{}
54 | req, err := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
55 | if err != nil {
56 | return
57 | }
58 |
59 | req.Header.Set("User-Agent", userAgent)
60 | req.Header.Set("Cookie", cookie)
61 | req.Header.Set("Content-Type", ContentType)
62 |
63 | resp, err := client.Do(req)
64 | if err != nil {
65 | return
66 | }
67 | defer resp.Body.Close()
68 |
69 | status = resp.StatusCode
70 | body, err = ioutil.ReadAll(resp.Body)
71 | if err != nil {
72 | return
73 | }
74 |
75 | return
76 | }
77 |
78 | // Send 发送预约请求
79 | func Send(period string, token string) (status int, id string, info string, err error) {
80 | values := make(url.Values)
81 | values.Set("period", period)
82 |
83 | status, body, err := Post("http://wx.bupt.edu.cn/bathroom/submit", values, UserAgent, token)
84 | if err != nil {
85 | return
86 | }
87 | if DEBUG {
88 | fmt.Printf("%s\n", body)
89 | }
90 |
91 | _id := idReg.FindSubmatch(body)
92 | if len(_id) > 1 {
93 | id = string(_id[1])
94 | }
95 | _info := infoReg.FindSubmatch(body)
96 | if len(_info) > 1 {
97 | info = string(_info[1])
98 | }
99 |
100 | return
101 | }
102 |
103 | // Keep 用户 token 保活
104 | func Keep(token string) (status int, id string, err error) {
105 | status, body, err := Get("http://wx.bupt.edu.cn/bathroom/index", UserAgent, token)
106 | if err != nil {
107 | return
108 | }
109 | if DEBUG {
110 | fmt.Printf("%s\n", body)
111 | }
112 |
113 | _id := idReg.FindSubmatch(body)
114 | if len(_id) > 1 {
115 | id = string(_id[1])
116 | }
117 |
118 | return
119 | }
120 |
121 | func read(file string) (tokens []string, err error) {
122 | tokens = make([]string, 0)
123 | data, err := ioutil.ReadFile(file)
124 | if err != nil {
125 | return
126 | }
127 | temp := strings.Split(string(data), "\n")
128 | for _, item := range temp {
129 | if item != "" {
130 | tokens = append(tokens, item)
131 | }
132 | }
133 |
134 | return
135 | }
136 |
137 | func main() {
138 | var debug bool
139 | var tokenFile string
140 | var submit bool
141 | flag.BoolVar(&debug, "debug", false, "调试模式")
142 | flag.BoolVar(&debug, "d", false, "调试模式")
143 | flag.BoolVar(&submit, "submit", false, "预约模式")
144 | flag.BoolVar(&submit, "s", false, "预约模式")
145 | flag.StringVar(&tokenFile, "tokens", "", "Token 文件路径")
146 | flag.StringVar(&tokenFile, "t", "", "Token 文件路径")
147 | flag.Parse()
148 |
149 | DEBUG = debug
150 |
151 | period := time.Now().AddDate(0, 0, 1).Format("2006-01-02") + " 21:00:00"
152 |
153 | tokens, err := read(tokenFile)
154 | if err != nil {
155 | fmt.Println(err)
156 | }
157 |
158 | fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
159 |
160 | if submit {
161 | for _, token := range tokens {
162 | count := 100
163 | for count >= 0 {
164 | count--
165 |
166 | status, id, info, err := Send(period, token)
167 | if status != 200 || id == "" {
168 | fmt.Printf("Status %d, ID %s Info %s\n%s\n", status, id, info, err)
169 | } else {
170 | fmt.Println(id, info)
171 | break
172 | }
173 | time.Sleep(time.Second * 1)
174 | }
175 | }
176 | } else {
177 | for _, token := range tokens {
178 | status, id, err := Keep(token)
179 | if id == "" {
180 | fmt.Printf("Status %d, ID %s\n%s\n", status, id, err)
181 | } else {
182 | fmt.Println(id, "ok")
183 | }
184 | }
185 |
186 | }
187 | fmt.Printf("Finished at %s\n\n\n", time.Now().Format("2006-01-02 15:04:05"))
188 | }
189 |
--------------------------------------------------------------------------------
/bath/go/tokens.txt:
--------------------------------------------------------------------------------
1 | laravel_session=xxxxx
--------------------------------------------------------------------------------
/bath/python/README.md:
--------------------------------------------------------------------------------
1 | # Python 语言版浴室预约脚本
2 |
3 | 运行参数:
4 | - `today` 预约今日的浴室
5 | - `tomorrow` 预约明日的浴室
6 | - 如果存在形如 `21:00:00` 的参数,则会预约对应时间的浴室(需要确保输入合法)
7 | - `laravel_session=` 要预约用户的 Token 数据
8 | - `debug` 调试模式
9 |
--------------------------------------------------------------------------------
/bath/python/bath.py:
--------------------------------------------------------------------------------
1 | import re
2 | from time import sleep, time
3 | import requests
4 | import datetime
5 | import sys
6 |
7 | DEBUG = False
8 |
9 |
10 | def main(period, token):
11 | res = requests.post(
12 | "http://wx.bupt.edu.cn/bathroom/submit",
13 | data={
14 | "period": period
15 | },
16 | headers={
17 | "user-agent": "MicroMessenger",
18 | },
19 | cookies={
20 | "laravel_session": token
21 | },
22 | )
23 |
24 | if DEBUG or res.status_code == 200:
25 | print(res.text)
26 |
27 | print(res.status_code, re.findall(r'学工号: (\d+)
', res.text),
28 | re.findall(r'(.*)
', res.text))
29 |
30 | return res.status_code == 200
31 |
32 |
33 | if __name__ == "__main__":
34 | today = datetime.date.today()
35 | tomorrow = today+datetime.timedelta(days=1)
36 | at = today+datetime.timedelta(days=2)
37 |
38 | period = "21:00:00"
39 | token = ""
40 |
41 | rePeriod = r'^\d\d:\d\d:\d\d$'
42 | date = at
43 | for arg in sys.argv:
44 | if ("today" == arg):
45 | date = today
46 | if ("tomorrow" == arg):
47 | date = tomorrow
48 | if re.fullmatch(rePeriod, arg):
49 | period = arg
50 | if "laravel_session" in arg:
51 | token = arg.split("=")[1]
52 | if arg == "debug":
53 | DEBUG = True
54 | print("task:", date, period, "\n", token)
55 |
56 | while 1:
57 | if main("{} {}".format(date, period), token):
58 | break
59 | sleep(1)
60 |
--------------------------------------------------------------------------------
/check/README.md:
--------------------------------------------------------------------------------
1 | # 疫情打卡脚本
2 |
3 | 自动在疫情防控通打卡
4 |
5 | 账号为学号
6 | 密码为服务门户密码(默认为身份证后8位)
7 |
8 | 账户和密码使用空格分割存放在`users.txt`中,一行一个用户
9 |
10 | 疫情打卡会使用前一天的数据结合当日需要修改的参数进行打卡,因此如果有部分项目需要修改,只需要有一天手动打卡即可,后续都会继续沿用前一日的数据
--------------------------------------------------------------------------------
/check/check.crontab.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #export PYTHONPATH="/usr/lib/python38.zip:/usr/lib/python3.8:/usr/lib/python3.8/lib-dynload:/home/ubuntu/.local/lib/python3.8/site-packages:/usr/local/lib/python3.8/dist-packages:/usr/lib/python3/dist-packages"
4 |
5 | SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
6 |
7 | date '+%Y-%m-%d %H:%M:%S' >> $SHELL_FOLDER/log.log
8 | python3 $SHELL_FOLDER/check.py 1>>$SHELL_FOLDER/log.log 2>>$SHELL_FOLDER/error.log
--------------------------------------------------------------------------------
/check/check.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import datetime
3 | import re
4 | import json
5 | import os
6 | import time
7 | import random
8 |
9 |
10 | oldKeys = [
11 | "ismoved", "jhfjrq", "jhfjjtgj", "jhfjhbcc", "sfxk", "xkqq", "szgj", "szcs", "zgfxdq", "mjry", "csmjry", "uid", "tw", "sfcxtz", "sfyyjc", "jcjgqr", "jcjg", "sfjcbh", "sfcxzysx", "qksm", "remark", "address", "area", "province", "city", "geo_api_info", "sfzx", "sfjcwhry", "sfcyglq", "gllx",
12 | "glksrq", "jcbhlx", "jcbhrq", "sftjwh", "sftjhb", "fxyy", "bztcyy", "fjsj", "sfjchbry", "sfjcqz", "jcqzrq", "jcwhryfs", "jchbryfs", "xjzd", "sfsfbh", "jhfjsftjwh", "jhfjsftjhb", "szsqsfybl", "sfygtjzzfj", "gtjzzfjsj", "sfsqhzjkk", "sqhzjkkys", "created_uid", "gwszdd", "sfyqjzgc", "jrsfqzys", "jrsfqzfy"
13 | ]
14 | defaultKeys = [
15 | "date", "created", "id",
16 | ]
17 |
18 |
19 | def login(session, username: str, password: str):
20 | resp = session.get("https://auth.bupt.edu.cn/authserver/login", data={
21 | "username": username,
22 | "password": password,
23 | })
24 |
25 | result =re.findall( r'', resp.text)
26 | if len(result) > 0:
27 | execution = result[0]
28 | else:
29 | execution = ""
30 |
31 | resp = session.post("https://auth.bupt.edu.cn/authserver/login", data={
32 | "username": username,
33 | "password": password,
34 | "submit": "登录",
35 | "type": "username_password",
36 | "execution": execution,
37 | "_eventId": "submit",
38 | })
39 |
40 | return True
41 | if resp.json()["e"] == 0:
42 | return True
43 | else:
44 | print(resp.text)
45 | return False
46 |
47 | def check(username: str, password: str):
48 | session = requests.Session()
49 |
50 | if login(session, username, password):
51 | print(username, "登录成功")
52 | else:
53 | print(username, "登录失败")
54 | return
55 |
56 | resp = session.get("https://app.bupt.edu.cn/ncov/wap/default/index")
57 | matchDefault = re.findall(r'var def = (.*);\n', resp.text)
58 | if (len(matchDefault) == 0):
59 | print("获取默认信息失败")
60 | return
61 | default = json.loads(matchDefault[0])
62 |
63 | matchOld = re.findall(r'oldInfo: (.*),\n', resp.text)
64 | if (len(matchOld) == 0):
65 | print("获取上次信息失败")
66 | return
67 | oldInfo = json.loads(matchOld[0])
68 |
69 | realnames = re.findall(r'realname: "(.*)",', resp.text)
70 | realname = "获取名称失败"
71 | if len(realnames) > 0:
72 | realname = realnames[0]
73 |
74 | data = {}
75 | for k in oldInfo:
76 | data[k] = oldInfo.get(k, "")
77 | for k in defaultKeys:
78 | data[k] = default.get(k, "")
79 |
80 | resp = session.post(
81 | "https://app.bupt.edu.cn/ncov/wap/default/save", data=data)
82 |
83 | j = resp.json()
84 | if j.get("e", 1) == 0:
85 | print(realname, "填报成功", oldInfo.get("address", ""))
86 | else:
87 | print(realname, "填报失败", j.get("m", ""))
88 |
89 |
90 | if __name__ == "__main__":
91 | random.seed(time.time())
92 | with open(os.path.join(os.path.dirname(__file__), "users.txt")) as f:
93 | users = f.read().split("\n")
94 | random.shuffle(users)
95 | for u in users:
96 | sleepTime = random.randint(10,30)
97 | time.sleep(sleepTime)
98 | try:
99 | if u != "":
100 | username, password = u.split(" ")
101 | print(username+' sleep time:'+str(sleepTime))
102 | check(username, password)
103 | except Exception as e:
104 | print(e)
105 |
--------------------------------------------------------------------------------
/check/users.txt:
--------------------------------------------------------------------------------
1 | 2019111111 11111111
2 | 2019111112 11111112
3 |
--------------------------------------------------------------------------------
/crontab.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 运行该文件将相关定时任务追加至 crontab 中
3 |
4 | SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
5 |
6 | crontab -l > ./crontab.temp
7 | echo "
8 | # bupt
9 | 30 0 * * * /bin/bash $SHELL_FOLDER/check/check.crontab.bash
10 | 30 6 * * * /bin/bash $SHELL_FOLDER/check/check.crontab.bash
11 | 0 7 * * * /bin/bash $SHELL_FOLDER/leave/leave.crontab.bash
12 | " >> ./crontab.temp
13 | crontab ./crontab.temp
14 | rm crontab.temp
15 |
16 | crontab -l
--------------------------------------------------------------------------------
/leave/README.md:
--------------------------------------------------------------------------------
1 | # 自动请假脚本
2 |
3 | 在`users.txt`中以 yaml 格式填入数据,每个用户包含以下字段
4 | - username: 用户名
5 | - password: 服务门户密码(默认身份证后 8 位)
6 | - phone: 手机号
7 | - position: 要去的地方(不填写默认实验室)
8 | - reason: 出校原因(不填写默认科研)
9 | - school: 校区(不填写默认西土城)
10 | - teacher_uid: 辅导员 id(需要自己在相应页面按 F12 查看,虽然有查询接口,但是有重名概率)
11 | - teacher_name: 辅导员姓名
12 |
13 | 每两个用户使用单独的一行`---`分割
14 |
15 | ```
16 | username: "2019111111"
17 | password: "11111111"
18 | phone: "19999999999"
19 | position: "实验室"
20 | reason: "科研"
21 | school: "西土城"
22 | teacher_uid: 000
23 | teacher_name: "xxx"
24 | ```
--------------------------------------------------------------------------------
/leave/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 请假外出、返校权限查询通行码
8 |
182 |
183 |
184 |
185 | 网页由 service.bupt.edu.cn 提供
186 |
187 |
188 |
191 |
姓名
192 |
川建国
193 |
学院
194 |
计算机学院(国家示范性软件学院)
195 |
状态码
196 |

198 |
199 |
状态
200 |
允许入校
201 |
学工号
202 |
2019123321
203 |
出入校时间
204 |
2020-09-07 00:00:00
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
216 |
217 |
218 |
×
219 |
220 |
221 |
222 | 姓名 |
223 | 川建国 |
224 | 学工号 |
225 | 2019123321 |
226 |
227 |
228 | 状态二维码 |
229 |
231 | |
232 |
233 |
234 | 出入校时间 |
235 | 2020-09-07 00:00:00 |
236 |
237 |
238 | 学院 |
239 | 计算机学院(国家示范性软件学院) |
240 |
241 |
242 |
243 |
244 |
245 |
347 |
348 |
349 |
350 |
--------------------------------------------------------------------------------
/leave/leave.crontab.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #export PYTHONPATH="/usr/lib/python38.zip:/usr/lib/python3.8:/usr/lib/python3.8/lib-dynload:/home/ubuntu/.local/lib/python3.8/site-packages:/usr/local/lib/python3.8/dist-packages:/usr/lib/python3/dist-packages"
4 | SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
5 |
6 | date '+%Y-%m-%d %H:%M:%S' >> $SHELL_FOLDER/log.log
7 | python3 $SHELL_FOLDER/leave.py 1>>$SHELL_FOLDER/log.log 2>>$SHELL_FOLDER/error.log
--------------------------------------------------------------------------------
/leave/leave.py:
--------------------------------------------------------------------------------
1 | import json
2 | from urllib import parse
3 | import requests
4 | import datetime
5 | import re
6 | import yaml
7 | import os
8 |
9 | session = requests.Session()
10 | schools = {
11 | "沙河": {"name": "沙河校区", "value": "1", "default": 0, "imgdata": ""},
12 | "西土城": {"name": "西土城校区", "value": "2", "default": 0, "imgdata": ""},
13 | }
14 |
15 |
16 | def login(username: str, password: str):
17 | session.cookies.clear()
18 | resp = session.get("https://auth.bupt.edu.cn/authserver/login")
19 | matchLT = re.findall(
20 | r'', resp.text)
21 | if len(matchLT) == 0:
22 | print("登录 CSRF 加载错误")
23 | return ""
24 | lt = matchLT[0]
25 |
26 | resp = session.post(
27 | "https://auth.bupt.edu.cn/authserver/login?service=https%3A%2F%2Fme.bupt.edu.cn%2Fsite%2Flogin%2Fcas-login",
28 | data={
29 | "username": username,
30 | "password": password,
31 | "lt": lt,
32 | "execution": "e1s1",
33 | "_eventId": "submit",
34 | "rmShown": 1,
35 | })
36 |
37 | matchUserInfo = re.findall(
38 | r'\s*
\s*([^\s]*)\s*\s*
',
39 | resp.text
40 | )
41 | if len(matchUserInfo) != 0:
42 | return matchUserInfo[0]
43 | return ""
44 |
45 |
46 | def getCollege():
47 | resp = session.get("https://service.bupt.edu.cn/site/user/get-name")
48 | return resp.json()["d"]["college"]
49 |
50 |
51 | def leave(
52 | username: str,
53 | password: str,
54 | phone: str,
55 | position: str,
56 | reason: str,
57 | school: object,
58 | teacher: object
59 | ):
60 | name = login(username, password)
61 | if name == "":
62 | print(username, "登录失败")
63 | return
64 | print(name, "登录成功")
65 |
66 | college = getCollege()
67 |
68 | tomorrow = datetime.datetime.now() + datetime.timedelta(days=1)
69 |
70 | date = tomorrow.replace(
71 | hour=0, minute=0, second=0,
72 | microsecond=0
73 | ).isoformat(timespec="microseconds")[:-7] + "+08:00"
74 |
75 | beginTime = tomorrow.replace(
76 | hour=7, minute=0, second=0, microsecond=0
77 | ).astimezone(
78 | tz=datetime.timezone.utc
79 | ).isoformat(timespec="microseconds").replace("000+00:00", "Z")
80 | endTime = tomorrow.replace(
81 | hour=23, minute=59, second=59, microsecond=0
82 | ).astimezone(
83 | tz=datetime.timezone.utc
84 | ).isoformat(timespec="microseconds").replace("000+00:00", "Z")
85 |
86 |
87 |
88 | data = {
89 | "data": {
90 | "app_id": "578",
91 | "node_id": "",
92 | "form_data": {
93 | "1716": {
94 | "Alert_67": "",
95 | "Count_74": {"type": 0, "value": 1}, # unused
96 | "Valudate_66": "", # unused
97 | "User_5": name,
98 | "User_7": username,
99 | "User_9": college,
100 | "User_11": phone,
101 | "Input_28": position,
102 | "Radio_52": {
103 | "value": "1",
104 | "name": "本人已阅读并承诺",
105 | },
106 | "Radio_73": {
107 | "value": "1",
108 | "name": "是",
109 | },
110 | "Calendar_47": endTime,
111 | "Calendar_50": beginTime,
112 | "Calendar_62": date,
113 | "Calendar_69": date, # unused
114 | "SelectV2_58": [schools[school]],
115 | "MultiInput_30": reason,
116 | "UserSearch_60": teacher,
117 | "UserSearch_73": teacher, # unused
118 | "Validate_63": "",
119 | "Alert_65": "",
120 | "Validate_66": "",
121 | "Variate_74": "否", # unused
122 | "DataSource_75": "" # unused
123 | }
124 | },
125 | "userview": 1,
126 | "special_approver": [
127 | {
128 | "node_key": "UserTask_100lwr4",
129 | "uids": [
130 | teacher.get("uid", "")
131 | ],
132 | "subprocessIndex": ""
133 | }
134 | ]
135 | }
136 | }
137 |
138 | resp = session.post(
139 | "https://service.bupt.edu.cn/site/apps/launch",
140 | data="data=" + parse.quote(str(data["data"]).replace(
141 | "'", '"').replace(" ", "")),
142 | headers={
143 | "Content-Type": "application/x-www-form-urlencoded",
144 | "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36 Edg/86.0.622.38",
145 | # "refer": "https://service.bupt.edu.cn/v2/matter/start?id=578",
146 | "x-requested-with": "XMLHttpRequest",
147 | # "accept": "application/json, text/plain, */*",
148 | }
149 | )
150 | resp.encoding = "utf-8"
151 | print(resp.text)
152 |
153 |
154 | if __name__ == "__main__":
155 | with open(os.path.join(os.path.dirname(__file__), "users.txt")) as f:
156 | users = yaml.load_all(f, Loader=yaml.FullLoader)
157 | for u in users:
158 | try:
159 | leave(
160 | username=u["username"],
161 | password=u["password"],
162 | phone=u["phone"],
163 | position=u.get("position", "实验室"),
164 | reason=u.get("reason", "科研"),
165 | school=u.get("school", "西土城"),
166 | teacher={
167 | "uid": u.get("teacher_uid", 0),
168 | "name": u.get("teacher_name", ""),
169 | "number": u.get("teacher_number", "")
170 | }
171 | )
172 | except Exception as e:
173 | print(e.print_exc())
174 |
--------------------------------------------------------------------------------
/leave/users.txt:
--------------------------------------------------------------------------------
1 | username: "2019111111"
2 | password: "11111111"
3 | phone: "19999999999"
4 | position: "实验室"
5 | reason: "科研"
6 | school: "西土城"
7 | teacher_uid: 000
8 | teacher_name: "xxx"
9 | teacher_number: "1234"
10 | ---
11 | username: "2019111111"
12 | password: "11111111"
13 | phone: "19999999999"
14 | position: "实验室"
15 | reason: "科研"
16 | school: "西土城"
17 | teacher_uid: 000
18 | teacher_name: "xxx"
19 | teacher_number: "1234"
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | requests
--------------------------------------------------------------------------------