From 49db618d62fe6df22274ff7856de099868de7766 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 16 Sep 2023 11:32:49 +0800 Subject: [PATCH 1/6] chore(deps-dev): bump @types/jsdom from 21.1.2 to 21.1.3 (#13314) * chore(deps-dev): bump @types/jsdom from 21.1.2 to 21.1.3 Bumps [@types/jsdom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jsdom) from 21.1.2 to 21.1.3. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jsdom) --- updated-dependencies: - dependency-name: "@types/jsdom" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- pnpm-lock.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fb050cdc3d9712..d38ebe99500b3b 100644 --- a/package.json +++ b/package.json @@ -157,7 +157,7 @@ "@types/fs-extra": "11.0.2", "@types/git-rev-sync": "2.0.0", "@types/imapflow": "1.0.13", - "@types/jsdom": "21.1.2", + "@types/jsdom": "21.1.3", "@types/json-bigint": "1.0.1", "@types/koa": "2.13.9", "@types/koa-basic-auth": "2.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8a040320bf9ce1..5640683401ff4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -224,8 +224,8 @@ devDependencies: specifier: 1.0.13 version: 1.0.13 '@types/jsdom': - specifier: 21.1.2 - version: 21.1.2 + specifier: 21.1.3 + version: 21.1.3 '@types/json-bigint': specifier: 1.0.1 version: 1.0.1 @@ -1516,8 +1516,8 @@ packages: '@types/istanbul-lib-report': 3.0.0 dev: true - /@types/jsdom@21.1.2: - resolution: {integrity: sha512-bGj+7TaCkOwkJfx7HtS9p22Ij0A2aKMuz8a1+owpkxa1wU/HUBy/WAXhdv90uDdVI9rSjGvUrXmLSeA9VP3JeA==} + /@types/jsdom@21.1.3: + resolution: {integrity: sha512-1zzqSP+iHJYV4lB3lZhNBa012pubABkj9yG/GuXuf6LZH1cSPIJBqFDrm5JX65HHt6VOnNYdTui/0ySerRbMgA==} dependencies: '@types/node': 20.5.6 '@types/tough-cookie': 4.0.3 From 9f7688334fd2fdd7f19f251696306f463dce469e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 16 Sep 2023 14:09:58 +0800 Subject: [PATCH 2/6] chore(deps-dev): bump @types/json-bigint from 1.0.1 to 1.0.2 (#13313) * chore(deps-dev): bump @types/json-bigint from 1.0.1 to 1.0.2 Bumps [@types/json-bigint](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/json-bigint) from 1.0.1 to 1.0.2. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/json-bigint) --- updated-dependencies: - dependency-name: "@types/json-bigint" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- pnpm-lock.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d38ebe99500b3b..45e35d5a25b32a 100644 --- a/package.json +++ b/package.json @@ -158,7 +158,7 @@ "@types/git-rev-sync": "2.0.0", "@types/imapflow": "1.0.13", "@types/jsdom": "21.1.3", - "@types/json-bigint": "1.0.1", + "@types/json-bigint": "1.0.2", "@types/koa": "2.13.9", "@types/koa-basic-auth": "2.0.4", "@types/koa-favicon": "2.0.22", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5640683401ff4f..bc8ce7f1d7f2a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -227,8 +227,8 @@ devDependencies: specifier: 21.1.3 version: 21.1.3 '@types/json-bigint': - specifier: 1.0.1 - version: 1.0.1 + specifier: 1.0.2 + version: 1.0.2 '@types/koa': specifier: 2.13.9 version: 2.13.9 @@ -1524,8 +1524,8 @@ packages: parse5: 7.1.2 dev: true - /@types/json-bigint@1.0.1: - resolution: {integrity: sha512-zpchZLNsNuzJHi6v64UBoFWAvQlPhch7XAi36FkH6tL1bbbmimIF+cS7vwkzY4u5RaSWMoflQfu+TshMPPw8uw==} + /@types/json-bigint@1.0.2: + resolution: {integrity: sha512-ZXqZc1YeBj1B2my/a/f5PWpNemgIb1r5s3cALPvsMqoGEZ0NOEo1UxrSRUEZr0EtChy1BH/CuORiYuvYr4/4Fw==} dev: true /@types/json-schema@7.0.12: From 0d0f482ba7a9968c1065cdc618d547c8050eb0b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A0=E9=99=A5=E9=9B=BB=E6=B0=97?= Date: Sun, 17 Sep 2023 00:31:12 +0800 Subject: [PATCH 3/6] fix(route): update mixcloud queries (#13319) --- lib/v2/mixcloud/index.js | 27 +-- lib/v2/mixcloud/queries.js | 366 +++++++++++++++++++------------------ 2 files changed, 192 insertions(+), 201 deletions(-) diff --git a/lib/v2/mixcloud/index.js b/lib/v2/mixcloud/index.js index b4d4e7d7b1de36..243ef3c56e477a 100644 --- a/lib/v2/mixcloud/index.js +++ b/lib/v2/mixcloud/index.js @@ -6,6 +6,7 @@ const { queries } = require('./queries'); module.exports = async (ctx) => { const host = 'https://www.mixcloud.com'; const imageBaseURL = 'https://thumbnailer.mixcloud.com/unsafe/480x480/'; + const graphqlURL = 'https://app.mixcloud.com/graphql'; const headers = { Referer: host, 'Content-Type': 'application/json', @@ -40,7 +41,6 @@ module.exports = async (ctx) => { username: ctx.params.username, }, orderBy: 'LATEST', - audioTypes: ['SHOW'], }, }, favorites: { @@ -59,37 +59,20 @@ module.exports = async (ctx) => { }, }, }, - profile: { - query: queries.profile.query, - variables: { - lookup: { - username: ctx.params.username, - }, - }, - }, }; - const profile = ( - await got({ - method: 'post', - url: `${host}/graphql`, - json: payloads.profile, - headers, - }) - ).data.data; - - const biog = profile.user.biog; - const image = `${imageBaseURL}${profile.user.picture.urlRoot}`; - const data = ( await got({ method: 'post', - url: `${host}/graphql`, + url: graphqlURL, json: payloads[type], headers, }) ).data.data; + const biog = data.user.biog; + const image = `${imageBaseURL}${data.user.picture.urlRoot}`; + // https://github.com/ytdl-org/youtube-dl/blob/f1487d4fca40fd37d735753e24a7bae53a1b1513/youtube_dl/extractor/mixcloud.py#L72-L79 const decryptionKey = 'IFYOUWANTTHEARTISTSTOGETPAIDDONOTDOWNLOADFROMMIXCLOUD'; const decryptXorCipher = (key, cipherText) => { diff --git a/lib/v2/mixcloud/queries.js b/lib/v2/mixcloud/queries.js index 72b652b705340e..2102891a8888a7 100644 --- a/lib/v2/mixcloud/queries.js +++ b/lib/v2/mixcloud/queries.js @@ -1,6 +1,8 @@ const queries = { stream: { - query: `query UserStreamQuery($lookup: UserLookup!) { + query: `query UserStreamQuery( + $lookup: UserLookup! + ) { user: userLookup(lookup: $lookup) { username ...UserStreamPage_user @@ -27,6 +29,9 @@ const queries = { username isSubscribedTo isViewer + affiliateUsers { + totalCount + } } ...AudioCardFavoriteButton_cloudcast ...AudioCardRepostButton_cloudcast @@ -176,6 +181,7 @@ const queries = { isPublic slug description + audioType picture { urlRoot } @@ -209,6 +215,28 @@ const queries = { ...AudioCardTags_cloudcast } + fragment AudioCardSubLinks_cloudcast on Cloudcast { + id + isExclusive + owner { + id + displayName + username + ...Hovercard_user + } + creatorAttributions(first: 2) { + totalCount + edges { + node { + id + displayName + username + ...Hovercard_user + } + } + } + } + fragment AudioCardTags_cloudcast on Cloudcast { tags(country: "GLOBAL") { tag { @@ -224,18 +252,20 @@ const queries = { slug name audioType + audioQuality isLiveRecording isExclusive owner { id - displayName username - ...Hovercard_user ...UserBadge_user } + creatorAttributions(first: 2) { + totalCount + } + ...AudioCardSubLinks_cloudcast ...AudioCardPlayButton_cloudcast ...ExclusiveCloudcastBadgeContainer_cloudcast - ...CloudcastHQAudio_cloudcast } fragment AudioCard_cloudcast on Cloudcast { @@ -275,10 +305,6 @@ const queries = { } } - fragment CloudcastHQAudio_cloudcast on Cloudcast { - audioQuality - } - fragment ExclusiveCloudcastBadgeContainer_cloudcast on Cloudcast { isExclusive isExclusivePreviewOnly @@ -301,6 +327,17 @@ const queries = { } } + fragment ShareAudioCardList_user on User { + biog + username + displayName + id + isUploader + picture { + urlRoot + } + } + fragment UGCImage_picture on Picture { urlRoot primaryColor @@ -316,15 +353,16 @@ const queries = { id displayName username + ...ShareAudioCardList_user stream(first: 10) { edges { - cursor repostedBy node { id ...AudioCard_cloudcast __typename } + cursor } pageInfo { endCursor @@ -341,11 +379,10 @@ const queries = { query: `query UserUploadsQuery( $lookup: UserLookup! $orderBy: CloudcastOrderByEnum - $audioTypes: [AudioTypeEnum!] ) { user: userLookup(lookup: $lookup) { username - ...UserUploadsPage_user_3HcCKF + ...UserUploadsPage_user_7FfCv id } viewer { @@ -369,6 +406,9 @@ const queries = { username isSubscribedTo isViewer + affiliateUsers { + totalCount + } } ...AudioCardFavoriteButton_cloudcast ...AudioCardRepostButton_cloudcast @@ -518,6 +558,7 @@ const queries = { isPublic slug description + audioType picture { urlRoot } @@ -551,6 +592,28 @@ const queries = { ...AudioCardTags_cloudcast } + fragment AudioCardSubLinks_cloudcast on Cloudcast { + id + isExclusive + owner { + id + displayName + username + ...Hovercard_user + } + creatorAttributions(first: 2) { + totalCount + edges { + node { + id + displayName + username + ...Hovercard_user + } + } + } + } + fragment AudioCardTags_cloudcast on Cloudcast { tags(country: "GLOBAL") { tag { @@ -566,18 +629,20 @@ const queries = { slug name audioType + audioQuality isLiveRecording isExclusive owner { id - displayName username - ...Hovercard_user ...UserBadge_user } + creatorAttributions(first: 2) { + totalCount + } + ...AudioCardSubLinks_cloudcast ...AudioCardPlayButton_cloudcast ...ExclusiveCloudcastBadgeContainer_cloudcast - ...CloudcastHQAudio_cloudcast } fragment AudioCard_cloudcast on Cloudcast { @@ -617,10 +682,6 @@ const queries = { } } - fragment CloudcastHQAudio_cloudcast on Cloudcast { - audioQuality - } - fragment ExclusiveCloudcastBadgeContainer_cloudcast on Cloudcast { isExclusive isExclusivePreviewOnly @@ -643,6 +704,17 @@ const queries = { } } + fragment ShareAudioCardList_user on User { + biog + username + displayName + id + isUploader + picture { + urlRoot + } + } + fragment UGCImage_picture on Picture { urlRoot primaryColor @@ -654,16 +726,13 @@ const queries = { hasPremiumFeatures } - fragment UserUploadsPage_user_3HcCKF on User { + fragment UserUploadsPage_user_7FfCv on User { id displayName username - uploads( - first: 10 - orderBy: $orderBy - audioTypes: $audioTypes - isPublic: true - ) { + isViewer + ...ShareAudioCardList_user + uploads(first: 10, isPublic: true, orderBy: $orderBy, audioTypes: [SHOW]) { edges { node { ...AudioCard_cloudcast @@ -684,7 +753,9 @@ const queries = { }`, }, favorites: { - query: `query UserFavoritesQuery($lookup: UserLookup!) { + query: `query UserFavoritesQuery( + $lookup: UserLookup! + ) { user: userLookup(lookup: $lookup) { username hiddenFavorites: favorites { @@ -714,6 +785,9 @@ const queries = { username isSubscribedTo isViewer + affiliateUsers { + totalCount + } } ...AudioCardFavoriteButton_cloudcast ...AudioCardRepostButton_cloudcast @@ -863,6 +937,7 @@ const queries = { isPublic slug description + audioType picture { urlRoot } @@ -896,6 +971,28 @@ const queries = { ...AudioCardTags_cloudcast } + fragment AudioCardSubLinks_cloudcast on Cloudcast { + id + isExclusive + owner { + id + displayName + username + ...Hovercard_user + } + creatorAttributions(first: 2) { + totalCount + edges { + node { + id + displayName + username + ...Hovercard_user + } + } + } + } + fragment AudioCardTags_cloudcast on Cloudcast { tags(country: "GLOBAL") { tag { @@ -911,18 +1008,20 @@ const queries = { slug name audioType + audioQuality isLiveRecording isExclusive owner { id - displayName username - ...Hovercard_user ...UserBadge_user } + creatorAttributions(first: 2) { + totalCount + } + ...AudioCardSubLinks_cloudcast ...AudioCardPlayButton_cloudcast ...ExclusiveCloudcastBadgeContainer_cloudcast - ...CloudcastHQAudio_cloudcast } fragment AudioCard_cloudcast on Cloudcast { @@ -962,10 +1061,6 @@ const queries = { } } - fragment CloudcastHQAudio_cloudcast on Cloudcast { - audioQuality - } - fragment ExclusiveCloudcastBadgeContainer_cloudcast on Cloudcast { isExclusive isExclusivePreviewOnly @@ -988,6 +1083,17 @@ const queries = { } } + fragment ShareAudioCardList_user on User { + biog + username + displayName + id + isUploader + picture { + urlRoot + } + } + fragment UGCImage_picture on Picture { urlRoot primaryColor @@ -1004,6 +1110,7 @@ const queries = { displayName username isViewer + ...ShareAudioCardList_user favorites(first: 10) { edges { node { @@ -1028,7 +1135,9 @@ const queries = { }`, }, listens: { - query: `query UserListensQuery($lookup: UserLookup!) { + query: `query UserListensQuery( + $lookup: UserLookup! + ) { user: userLookup(lookup: $lookup) { username hiddenListeningHistory: listeningHistory { @@ -1058,6 +1167,9 @@ const queries = { username isSubscribedTo isViewer + affiliateUsers { + totalCount + } } ...AudioCardFavoriteButton_cloudcast ...AudioCardRepostButton_cloudcast @@ -1207,6 +1319,7 @@ const queries = { isPublic slug description + audioType picture { urlRoot } @@ -1240,6 +1353,28 @@ const queries = { ...AudioCardTags_cloudcast } + fragment AudioCardSubLinks_cloudcast on Cloudcast { + id + isExclusive + owner { + id + displayName + username + ...Hovercard_user + } + creatorAttributions(first: 2) { + totalCount + edges { + node { + id + displayName + username + ...Hovercard_user + } + } + } + } + fragment AudioCardTags_cloudcast on Cloudcast { tags(country: "GLOBAL") { tag { @@ -1255,18 +1390,20 @@ const queries = { slug name audioType + audioQuality isLiveRecording isExclusive owner { id - displayName username - ...Hovercard_user ...UserBadge_user } + creatorAttributions(first: 2) { + totalCount + } + ...AudioCardSubLinks_cloudcast ...AudioCardPlayButton_cloudcast ...ExclusiveCloudcastBadgeContainer_cloudcast - ...CloudcastHQAudio_cloudcast } fragment AudioCard_cloudcast on Cloudcast { @@ -1306,10 +1443,6 @@ const queries = { } } - fragment CloudcastHQAudio_cloudcast on Cloudcast { - audioQuality - } - fragment ExclusiveCloudcastBadgeContainer_cloudcast on Cloudcast { isExclusive isExclusivePreviewOnly @@ -1332,6 +1465,17 @@ const queries = { } } + fragment ShareAudioCardList_user on User { + biog + username + displayName + id + isUploader + picture { + urlRoot + } + } + fragment UGCImage_picture on Picture { urlRoot primaryColor @@ -1348,10 +1492,10 @@ const queries = { isViewer displayName username + ...ShareAudioCardList_user listeningHistory(first: 10) { totalCount edges { - cursor node { id cloudcast { @@ -1360,6 +1504,7 @@ const queries = { } __typename } + cursor } pageInfo { endCursor @@ -1376,143 +1521,6 @@ const queries = { ...AudioCard_viewer }`, }, - profile: { - query: `query UserProfileHeaderQuery($lookup: UserLookup!) { - user: userLookup(lookup: $lookup) { - id - displayName - username - isBranded - isStaff - isViewer - followers { - totalCount - } - hasCoverPicture - hasPremiumFeatures - hasProFeatures - picture { - primaryColor - ...UGCImage_picture - } - coverPicture { - urlRoot - } - ...ProfileNavigation_user - ...UserBadge_user - ...ShareUserButton_user - ...ProfileRegisterUpsellComponent_user - ...FollowButton_user - } - viewer { - ...ProfileRegisterUpsellComponent_viewer - ...FollowButton_viewer - id - } - } - - fragment FollowButton_user on User { - id - isFollowed - isFollowing - isViewer - followers { - totalCount - } - username - displayName - } - - fragment FollowButton_viewer on Viewer { - me { - id - } - } - - fragment ProfileNavigation_user on User { - id - username - stream { - totalCount - } - favorites { - totalCount - } - listeningHistory { - totalCount - } - uploads(audioTypes: [SHOW]) { - totalCount - } - tracks: uploads(audioTypes: [TRACK]) { - totalCount - } - posts { - totalCount - } - profileNavigation( - showsAudioTypes: [SHOW] - tracksAudioTypes: [TRACK] - streamAudioTypes: [SHOW, TRACK] - ) { - menuItems { - __typename - ... on NavigationItemInterface { - __isNavigationItemInterface: __typename - inDropdown - } - ... on HideableNavigationItemInterface { - __isHideableNavigationItemInterface: __typename - hidden - } - ... on PlaylistNavigationItem { - count - playlist { - id - name - slug - } - } - } - } - } - - fragment ProfileRegisterUpsellComponent_user on User { - id - displayName - followers { - totalCount - } - } - - fragment ProfileRegisterUpsellComponent_viewer on Viewer { - me { - id - } - } - - fragment ShareUserButton_user on User { - biog - username - displayName - id - isUploader - picture { - urlRoot - } - } - - fragment UGCImage_picture on Picture { - urlRoot - primaryColor - } - - fragment UserBadge_user on User { - hasProFeatures - isStaff - hasPremiumFeatures - }`, - }, }; module.exports = { From 5d5f63dcec5598c07b4d63a57852fc19673c8d10 Mon Sep 17 00:00:00 2001 From: Ermaotie <63703577+Ermaotie@users.noreply.github.com> Date: Sun, 17 Sep 2023 01:20:49 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feat(route):=20=E5=8D=8E=E5=8D=97=E7=90=86?= =?UTF-8?q?=E5=B7=A5=E5=A4=A7=E5=AD=A6=20-=20=E6=9C=BA=E6=A2=B0=E4=B8=8E?= =?UTF-8?q?=E6=B1=BD=E8=BD=A6=E5=B7=A5=E7=A8=8B=E5=AD=A6=E9=99=A2=20(#1331?= =?UTF-8?q?0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add route of SCUT SMAE * resolve 'Route' in md --- lib/v2/scut/maintainer.js | 1 + lib/v2/scut/radar.js | 34 +++++++++++++++++++ lib/v2/scut/router.js | 1 + lib/v2/scut/smae/notice.js | 54 +++++++++++++++++++++++++++++++ website/docs/routes/university.md | 10 ++++++ 5 files changed, 100 insertions(+) create mode 100644 lib/v2/scut/smae/notice.js diff --git a/lib/v2/scut/maintainer.js b/lib/v2/scut/maintainer.js index b66d98b34b8264..6c307266b0aafc 100644 --- a/lib/v2/scut/maintainer.js +++ b/lib/v2/scut/maintainer.js @@ -4,5 +4,6 @@ module.exports = { '/jwc/school/:category?': ['imkero', 'Rongronggg9'], '/scet/notice': ['railzy'], '/seie/news_center': ['auto-bot-ty'], + '/smae/:category?': ['Ermaotie'], '/yjs': ['shengmaosu'], }; diff --git a/lib/v2/scut/radar.js b/lib/v2/scut/radar.js index 0a52c32878e4ef..25a65f18b5c8ba 100644 --- a/lib/v2/scut/radar.js +++ b/lib/v2/scut/radar.js @@ -22,6 +22,40 @@ module.exports = { source: ['/ee/16285/list.htm'], target: '/scut/seie/news_center', }, + { + title: '机械与汽车工程学院 - 通知公告', + docs: 'https://docs.rsshub.app/routes/university#hua-nan-li-gong-da-xue', + source: ['/smae/:category/list.htm'], + target: (params) => { + let tid; + switch (params.category) { + case '20616': + tid = 'gwxx'; + break; + case '20617': + tid = 'djgz'; + break; + case '20622': + tid = 'rsgz'; + break; + case 'xsgz': + tid = 'xsgz'; + break; + case '20618': + tid = 'kysys'; + break; + case '20619': + tid = 'bksjw'; + break; + case '20620': + tid = 'yjsjw'; + break; + default: + return false; + } + return `/scut/smae/${tid}`; + }, + }, { title: '研究生院通知公告', docs: 'https://docs.rsshub.app/routes/university#hua-nan-li-gong-da-xue', diff --git a/lib/v2/scut/router.js b/lib/v2/scut/router.js index 6c2ecfda00a902..171153d5ec2aa5 100644 --- a/lib/v2/scut/router.js +++ b/lib/v2/scut/router.js @@ -4,5 +4,6 @@ module.exports = (router) => { router.get('/jwc/school/:category?', require('./jwc/school')); router.get('/scet/notice', require('./scet/notice')); router.get('/seie/news_center', require('./seie/news_center')); + router.get('/smae/:category?', require('./smae/notice')); router.get('/yjs', require('./yjs')); }; diff --git a/lib/v2/scut/smae/notice.js b/lib/v2/scut/smae/notice.js new file mode 100644 index 00000000000000..4a1535180746bf --- /dev/null +++ b/lib/v2/scut/smae/notice.js @@ -0,0 +1,54 @@ +// 导入必要的模组 +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); + +const categoryMap = { + gwxx: { title: '公务信息', tag: '20616' }, + djgz: { title: '党建工作', tag: '20617' }, + rsgz: { title: '人事工作', tag: '20622' }, + xsgz: { title: '学生工作', tag: 'xsgz' }, + kysys: { title: '科研实验室', tag: '20618' }, + bksjw: { title: '本科生教务', tag: '20619' }, + yjsjw: { title: '研究生教务', tag: '20620' }, +}; + +module.exports = async (ctx) => { + const baseUrl = 'http://www2.scut.edu.cn'; + + const categoryName = ctx.params.category || 'yjsjw'; + const categoryMeta = categoryMap[categoryName]; + const url = `${baseUrl}/smae/${categoryMeta.tag}/list.htm`; + + const { data: response } = await got(url); + const $ = cheerio.load(response); + const list = $('#wp_news_w6 ul li.news') + .toArray() + .map((item) => { + item = $(item); + const a = item.find('a'); + const pubDate = item.find('span.news_meta'); + return { + title: a.attr('title'), + link: `${baseUrl}${a.attr('href')}`, + pubDate: parseDate(pubDate.text()), + }; + }); + const items = await Promise.all( + list.map((item) => + ctx.cache.tryGet(item.link, async () => { + const { data: response } = await got(item.link); + const $ = cheerio.load(response); + + item.description = $('div.wp_articlecontent').html(); + + return item; + }) + ) + ); + ctx.state.data = { + title: `华南理工大学机械与汽车工程学院 - ${categoryMeta.title}`, + link: url, + item: items, + }; +}; diff --git a/website/docs/routes/university.md b/website/docs/routes/university.md index c4341e2706b642..bebec186e72765 100644 --- a/website/docs/routes/university.md +++ b/website/docs/routes/university.md @@ -1813,6 +1813,16 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS ::: +### 机械与汽车工程学院 - 通知公告 {#hua-nan-li-gong-da-xue-ji-xie-yu-qi-che-gong-cheng-xue-yuan-tong-zhi-gong-gao} + + + +| 公务信息 | 党建工作 | 人事工作 | 学生工作 | 科研实验室 | 本科生教务 | 研究生教务 | +| ------- | ------- | -------- | ------- | --------- | --------- | --------- | +| gwxx | djgz | rsgz | xsgz | kysys | bksjw | yjsjw | + + + ## 华南农业大学 {#hua-nan-nong-ye-da-xue} ### 华农研讯 {#hua-nan-nong-ye-da-xue-hua-nong-yan-xun} From aba9c2129033efe42438bdd058314c395d1fff2e Mon Sep 17 00:00:00 2001 From: nyaShine <127018961+nyaShine@users.noreply.github.com> Date: Sun, 17 Sep 2023 01:26:42 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20/sqmc/www=20=E6=96=B0=E4=B9=A1?= =?UTF-8?q?=E5=8C=BB=E5=AD=A6=E9=99=A2=E4=B8=89=E5=85=A8=E5=AD=A6=E9=99=A2?= =?UTF-8?q?=E5=AE=98=E7=BD=91=E4=BF=A1=E6=81=AF=20(#13322)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add /lsnu/jiaowc/tzgg 乐山师范学院教学部通知公告 * feat: /lsnu/jiaowc/tzgg/:category? 乐山师范学院教学部通知公告 * feat: /lsnu/jiaowc/tzgg 乐山师范学院教学部通知公告 * feat: /lsnu/jiaowc/tzgg 乐山师范学院教学部通知公告 * feat: /lsnu/jiaowc/tzgg 乐山师范学院教学部通知公告 * Revert "feat: /lsnu/jiaowc/tzgg 乐山师范学院教学部通知公告" This reverts commit 34c9411ef6ef3a5b92eb3f8995db5692fd12e3ec. * feat: /lsnu/jiaowc/tzgg 乐山师范学院教学部通知公告 * feat: /lsnu/jiaowc/tzgg 乐山师范学院教学部通知公告 * feat: /sqmc/www 新乡医学院三全学院官网信息 * feat: /sqmc/www 新乡医学院三全学院官网信息 * feat: /sqmc/www 新乡医学院三全学院官网信息 --------- --- lib/v2/sqmc/maintainer.js | 3 ++ lib/v2/sqmc/radar.js | 13 ++++++++ lib/v2/sqmc/router.js | 3 ++ lib/v2/sqmc/www.js | 49 +++++++++++++++++++++++++++++++ website/docs/routes/university.md | 12 ++++++++ 5 files changed, 80 insertions(+) create mode 100644 lib/v2/sqmc/maintainer.js create mode 100644 lib/v2/sqmc/radar.js create mode 100644 lib/v2/sqmc/router.js create mode 100644 lib/v2/sqmc/www.js diff --git a/lib/v2/sqmc/maintainer.js b/lib/v2/sqmc/maintainer.js new file mode 100644 index 00000000000000..19cd9e5c883729 --- /dev/null +++ b/lib/v2/sqmc/maintainer.js @@ -0,0 +1,3 @@ +module.exports = { + '/www/:category?': ['nyaShine'], +}; diff --git a/lib/v2/sqmc/radar.js b/lib/v2/sqmc/radar.js new file mode 100644 index 00000000000000..0b10ff0c4a8699 --- /dev/null +++ b/lib/v2/sqmc/radar.js @@ -0,0 +1,13 @@ +module.exports = { + 'sqmc.edu.cn': { + _name: '新乡医学院三全学院', + '.': [ + { + title: '官网信息', + docs: 'https://docs.rsshub.app/university.html#xin-xiang-yi-xue-yuan-san-quan-xue-yuan', + source: ['/:category/list.htm'], + target: '/sqmc/www/:category?', + }, + ], + }, +}; diff --git a/lib/v2/sqmc/router.js b/lib/v2/sqmc/router.js new file mode 100644 index 00000000000000..d4a87dd6d2e564 --- /dev/null +++ b/lib/v2/sqmc/router.js @@ -0,0 +1,3 @@ +module.exports = function (router) { + router.get('/www/:category?', require('./www')); +}; diff --git a/lib/v2/sqmc/www.js b/lib/v2/sqmc/www.js new file mode 100644 index 00000000000000..3686eb44616e8b --- /dev/null +++ b/lib/v2/sqmc/www.js @@ -0,0 +1,49 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const timezone = require('@/utils/timezone'); +const { parseDate } = require('@/utils/parse-date'); + +module.exports = async (ctx) => { + const category = ctx.params.category || '3157'; + + const rootUrl = 'https://www.sqmc.edu.cn'; + const currentUrl = `${rootUrl}/${category}/list.htm`; + + const response = await got({ + method: 'get', + url: currentUrl, + }); + + const $ = cheerio.load(response.data); + const list = $('div#wp_news_w9 ul li').get(); + + ctx.state.data = { + title: `新乡医学院三全学院官网信息${$('title').text()}`, + link: currentUrl, + item: await Promise.all( + list.map(async (item) => { + item = $(item); + + const link = new URL(item.find('dt a').attr('href'), rootUrl).href; + const pubDate = parseDate(item.find('dd').eq(0).text(), 'YYYY-MM-DD'); + + const cache = await ctx.cache.tryGet(link, async () => { + const detailResponse = await got({ + method: 'get', + url: link, + }); + const content = cheerio.load(detailResponse.data); + + return { + title: item.find('dt a').text(), + description: content('div.Tr_Detail').html(), + link, + pubDate: timezone(pubDate, +8), + }; + }); + + return cache; + }) + ), + }; +}; diff --git a/website/docs/routes/university.md b/website/docs/routes/university.md index bebec186e72765..556070869c345c 100644 --- a/website/docs/routes/university.md +++ b/website/docs/routes/university.md @@ -3434,6 +3434,18 @@ jsjxy.hbut.edu.cn 证书链不全,自建 RSSHub 可设置环境变量 NODE_TLS +## 新乡医学院三全学院 {#xin-xiang-yi-xue-yuan-san-quan-xue-yuan} + +### 官网信息 {#xin-xiang-yi-xue-yuan-san-quan-xue-yuan-guan-wang-xin-xi} + + + +| 学校要闻 | 通知 | 学术讲座 | 基层风采书院 | 基层风采院系 | 外媒报道 | 三全学院报 | +| -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| 3157 | 3187 | 3188 | 3185 | 3186 | 3199 | 3200 | + + + ## 信阳师范学院 {#xin-yang-shi-fan-xue-yuan} ### 高等教育自学考试办公室 {#xin-yang-shi-fan-xue-yuan-gao-deng-jiao-yu-zi-xue-kao-shi-ban-gong-shi} From b9604caaefdf5d4c7b16d034339cb7af3373a1a2 Mon Sep 17 00:00:00 2001 From: JimenezLi <75196426+JimenezLi@users.noreply.github.com> Date: Sun, 17 Sep 2023 01:54:27 +0800 Subject: [PATCH 6/6] feat(route): add alternativeto.net (#13320) * feat(route): add alternativeto.net * Update website/docs/routes/programming.md * Update website/docs/routes/programming.md --------- --- lib/v2/alternativeto/maintainer.js | 4 ++++ lib/v2/alternativeto/platform.js | 32 ++++++++++++++++++++++++++++++ lib/v2/alternativeto/radar.js | 19 ++++++++++++++++++ lib/v2/alternativeto/router.js | 4 ++++ lib/v2/alternativeto/software.js | 32 ++++++++++++++++++++++++++++++ lib/v2/alternativeto/utils.js | 22 ++++++++++++++++++++ website/docs/routes/programming.md | 18 +++++++++++++++++ 7 files changed, 131 insertions(+) create mode 100644 lib/v2/alternativeto/maintainer.js create mode 100644 lib/v2/alternativeto/platform.js create mode 100644 lib/v2/alternativeto/radar.js create mode 100644 lib/v2/alternativeto/router.js create mode 100644 lib/v2/alternativeto/software.js create mode 100644 lib/v2/alternativeto/utils.js diff --git a/lib/v2/alternativeto/maintainer.js b/lib/v2/alternativeto/maintainer.js new file mode 100644 index 00000000000000..7d03305836c8df --- /dev/null +++ b/lib/v2/alternativeto/maintainer.js @@ -0,0 +1,4 @@ +module.exports = { + '/software/:name/:routeParams?': ['JimenezLi'], + '/platform/:name/:routeParams?': ['JimenezLi'], +}; diff --git a/lib/v2/alternativeto/platform.js b/lib/v2/alternativeto/platform.js new file mode 100644 index 00000000000000..fef2e5525050ae --- /dev/null +++ b/lib/v2/alternativeto/platform.js @@ -0,0 +1,32 @@ +const { baseURL, puppeteerGet } = require('./utils'); +const cheerio = require('cheerio'); + +module.exports = async (ctx) => { + const name = ctx.params.name; + const query = new URLSearchParams(ctx.params.routeParams); + const link = `https://alternativeto.net/platform/${name}/?${query.toString()}`; + + // use Puppeteer due to the obstacle by cloudflare challenge + const html = await puppeteerGet(link, ctx.cache); + const $ = cheerio.load(html); + + ctx.state.data = { + title: $('.Heading_h1___Cf5Y').text().trim(), + description: $('.intro-text').text().trim(), + link, + item: $('.AppListItem_appInfo__h9cWP') + .toArray() + .map((element) => { + const item = $(element); + const title = item.find('.Heading_h2___LwQD').text().trim(); + const link = `${baseURL}${item.find('.Heading_h2___LwQD a').attr('href')}`; + const description = item.find('.AppListItem_description__wtODK').text().trim(); + + return { + title, + link, + description, + }; + }), + }; +}; diff --git a/lib/v2/alternativeto/radar.js b/lib/v2/alternativeto/radar.js new file mode 100644 index 00000000000000..e33e25eaf42708 --- /dev/null +++ b/lib/v2/alternativeto/radar.js @@ -0,0 +1,19 @@ +module.exports = { + 'alternativeto.net': { + _name: 'AlternativeTo', + www: [ + { + title: 'Software Alternatives', + docs: 'https://docs.rsshub.app/routes/programming#alternativeto-software-alternatives', + source: '/software/:name', + target: '/software/:name', + }, + { + title: 'Platform Software', + docs: 'https://docs.rsshub.app/routes/programming#alternativeto-platform-software', + source: '/platform/:name', + target: '/platform/:name', + }, + ], + }, +}; diff --git a/lib/v2/alternativeto/router.js b/lib/v2/alternativeto/router.js new file mode 100644 index 00000000000000..985663ff9c3567 --- /dev/null +++ b/lib/v2/alternativeto/router.js @@ -0,0 +1,4 @@ +module.exports = (router) => { + router.get('/software/:name/:routeParams?', require('./software')); + router.get('/platform/:name/:routeParams?', require('./platform')); +}; diff --git a/lib/v2/alternativeto/software.js b/lib/v2/alternativeto/software.js new file mode 100644 index 00000000000000..a54d54de71fa90 --- /dev/null +++ b/lib/v2/alternativeto/software.js @@ -0,0 +1,32 @@ +const { baseURL, puppeteerGet } = require('./utils'); +const cheerio = require('cheerio'); + +module.exports = async (ctx) => { + const name = ctx.params.name; + const query = new URLSearchParams(ctx.params.routeParams); + const link = `https://alternativeto.net/software/${name}/?${query.toString()}`; + + // use Puppeteer due to the obstacle by cloudflare challenge + const html = await puppeteerGet(link, ctx.cache); + const $ = cheerio.load(html); + + ctx.state.data = { + title: $('.Heading_h1___Cf5Y').text().trim(), + description: $('.intro-text').text().trim(), + link, + item: $('.AppListItem_appInfo__h9cWP') + .toArray() + .map((element) => { + const item = $(element); + const title = item.find('.Heading_h2___LwQD').text().trim(); + const link = `${baseURL}${item.find('.Heading_h2___LwQD a').attr('href')}`; + const description = item.find('.AppListItem_description__wtODK').text().trim(); + + return { + title, + link, + description, + }; + }), + }; +}; diff --git a/lib/v2/alternativeto/utils.js b/lib/v2/alternativeto/utils.js new file mode 100644 index 00000000000000..1ecbc02434cda2 --- /dev/null +++ b/lib/v2/alternativeto/utils.js @@ -0,0 +1,22 @@ +const baseURL = 'https://alternativeto.net'; + +const puppeteerGet = (url, cache) => + cache.tryGet(url, async () => { + const browser = await require('@/utils/puppeteer')(); + const page = await browser.newPage(); + await page.setRequestInterception(true); + page.on('request', (request) => { + request.resourceType() === 'document' ? request.continue() : request.abort(); + }); + await page.goto(url, { + waitUntil: 'domcontentloaded', + }); + const html = await page.evaluate(() => document.documentElement.innerHTML); + browser.close(); + return html; + }); + +module.exports = { + baseURL, + puppeteerGet, +}; diff --git a/website/docs/routes/programming.md b/website/docs/routes/programming.md index c82c88b2f39007..6163e73cc2c2c2 100644 --- a/website/docs/routes/programming.md +++ b/website/docs/routes/programming.md @@ -82,6 +82,24 @@ You have the option to utilize the main heading or use individual categories as +## AlternativeTo {#alternativeto} + +### Software Alternatives {#alternativeto-software-alternatives} + + + +> routeParms can be copied from original site URL, example: `/alternativeto/software/cpp/license=opensource&platform=windows` + + + +### Platform Software {#alternativeto-platform-software} + + + +> routeParms can be copied from original site URL, example: `/alternativeto/platform/firefox/license=free` + + + ## AtCoder {#atcoder} ### Present Contests {#atcoder-present-contests}