diff --git a/docs/university.md b/docs/university.md
index e7ddddc1cc..7a698d2b2e 100644
--- a/docs/university.md
+++ b/docs/university.md
@@ -1870,6 +1870,24 @@ type 列表:
+## 中国科学技术大学
+
+### 官网通知公告
+
+
+
+| 教学类 | 科研类 | 管理类 | 服务类 |
+| ------ | ------ | ------ | ------ |
+| jx | ky | gl | fw |
+
+### 教务处通知新闻
+
+
+
+| 信息 | 教学 | 考试 | 交流 |
+| -------- | -------- | -------- | -------- |
+| info | teaching | exam | exchange |
+
## 中国地质大学 (武汉)
### 研究生院综合通知公告
diff --git a/lib/router.js b/lib/router.js
index 2816a8af13..ee4cfff800 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -670,6 +670,10 @@ router.get('/cas/mesalab/kb', require('./routes/universities/cas/mesalab/kb'));
// 中国传媒大学
router.get('/cuc/yz', require('./routes/universities/cuc/yz'));
+// 中国科学技术大学
+router.get('/ustc/news/:type?', require('./routes/universities/ustc/index'));
+router.get('/ustc/jwc/:type?', require('./routes/universities/ustc/jwc/index'));
+
// 南京邮电大学
router.get('/njupt/jwc/:type?', require('./routes/universities/njupt/jwc'));
diff --git a/lib/routes/universities/ustc/index.js b/lib/routes/universities/ustc/index.js
new file mode 100644
index 0000000000..8bbf6ec4f3
--- /dev/null
+++ b/lib/routes/universities/ustc/index.js
@@ -0,0 +1,93 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const url = require('url');
+
+const notice_type = {
+ jx: { title: '中国科学技术大学 - 教学类通知', url: 'https://ustc.edu.cn/tzgg/jxltz.htm' },
+ ky: { title: '中国科学技术大学 - 科研类通知', url: 'https://ustc.edu.cn/tzgg/kyltz.htm' },
+ gl: { title: '中国科学技术大学 - 管理类通知', url: 'https://ustc.edu.cn/tzgg/glltz.htm' },
+ fw: { title: '中国科学技术大学 - 服务类通知', url: 'https://ustc.edu.cn/tzgg/fwltz.htm' },
+};
+
+// 对防抓的措施
+async function getCookie(ctx) {
+ const cache_key = `ustc-cookie-${new Date().toLocaleDateString()}`;
+ const cached_cookie = await ctx.cache.get(cache_key);
+ if (cached_cookie) {
+ return cached_cookie;
+ }
+ const { headers } = await got.get('https://ustc.edu.cn/system/resource/code/datainput.jsp', {
+ headers: { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36' },
+ });
+ const cookie = headers['set-cookie']
+ .filter((c) => c.match(/(user_trace_token|X_HTTP_TOKEN)/))
+ .map((c) => c.split(';')[0])
+ .join('; ');
+ ctx.cache.set(cache_key, cookie);
+ return cookie;
+}
+
+module.exports = async (ctx) => {
+ const type = ctx.params.type || 'gl';
+ // 发起 HTTP GET 请求
+ const response = await got({
+ method: 'get',
+ headers: {
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36',
+ cookie: await getCookie(ctx),
+ },
+ url: notice_type[type].url,
+ });
+
+ const $ = cheerio.load(response.data);
+ const list = $('table[portletmode=simpleList] > tbody > tr')
+ .map(function () {
+ const child = $(this).children();
+ const info = {
+ title: $(child[1]).find('a').text(),
+ link: $(child[1]).find('a').attr('href'),
+ date: new Date($(child[2]).text()).toUTCString(),
+ };
+ return info;
+ })
+ .get();
+
+ const out = await Promise.all(
+ list
+ .filter((item) => item.link)
+ .map(async (item) => {
+ const itemUrl = url.resolve(notice_type[type].url, item.link);
+ if (itemUrl.includes('tzggcontent.jsp') || itemUrl.includes('.ustc.edu.cn')) {
+ const single = {
+ title: item.title,
+ link: itemUrl,
+ description: item.title,
+ pubDate: item.date,
+ };
+ return Promise.resolve(single);
+ } else {
+ const cache = await ctx.cache.get(itemUrl);
+ if (cache) {
+ return Promise.resolve(JSON.parse(cache));
+ }
+ const response = await got.get(itemUrl);
+ const $ = cheerio.load(response.data);
+ const single = {
+ title: $('td[class=title] > span').text(),
+ link: itemUrl,
+ description: $('td[class=content]').html(),
+ pubDate: item.date,
+ };
+ ctx.cache.set(itemUrl, JSON.stringify(single));
+ return Promise.resolve(single);
+ }
+ })
+ );
+
+ ctx.state.data = {
+ title: notice_type[type].title,
+ description: notice_type[type].title,
+ link: notice_type[type].url,
+ item: out,
+ };
+};
diff --git a/lib/routes/universities/ustc/jwc/index.js b/lib/routes/universities/ustc/jwc/index.js
new file mode 100644
index 0000000000..f979128d1e
--- /dev/null
+++ b/lib/routes/universities/ustc/jwc/index.js
@@ -0,0 +1,60 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+const noticeUrl = 'https://www.teach.ustc.edu.cn/category/notice';
+const noticeType = { teaching: '教学', info: '信息', exam: '考试', exchange: '交流' };
+
+module.exports = async (ctx) => {
+ const type = ctx.params.type || '';
+ // 发起 HTTP GET 请求
+ const response = await got({
+ method: 'get',
+ headers: {
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36',
+ },
+ url: `${noticeUrl}${type === '' ? '' : '-' + type}`,
+ });
+
+ const $ = cheerio.load(response.data);
+ const list = $(`${type === '' ? 'ul[class="article-list with-tag"] > li' : 'ul[class=article-list] > li'}`)
+ .map(function () {
+ const child = $(this).children();
+ const info = {
+ title: `${type === '' ? $(child[0]).find('a').text() + ' - ' + $(child[1]).find('a').text() : $(child[0]).find('a').text()}`,
+ link: `${type === '' ? $(child[1]).find('a').attr('href') : $(child[0]).find('a').attr('href')}`,
+ };
+ return info;
+ })
+ .get();
+
+ const out = await Promise.all(
+ list
+ .filter((item) => item.link)
+ .map(async (item) => {
+ const itemUrl = item.link;
+ const cache = await ctx.cache.get(itemUrl);
+ if (cache) {
+ return Promise.resolve(JSON.parse(cache));
+ }
+ const response = await got.get(itemUrl);
+ const $ = cheerio.load(response.data);
+ const single = {
+ title: item.title,
+ link: itemUrl,
+ description: $('main[class=single]').html(),
+ pubDate: new Date($('li[class=meta-date]').text()).toUTCString(),
+ };
+ ctx.cache.set(itemUrl, JSON.stringify(single));
+ return Promise.resolve(single);
+ })
+ );
+
+ const desc = type === '' ? '中国科学技术大学教务处 - 通知新闻' : `中国科学技术大学教务处 - ${noticeType[type]}类通知`;
+
+ ctx.state.data = {
+ title: desc,
+ description: desc,
+ link: `${noticeUrl}${type === '' ? '' : '-' + type}`,
+ item: out,
+ };
+};