diff --git a/lib/v2/gocn/jobs.js b/lib/v2/gocn/jobs.js index 4faeeb68c1f43e..8f9b384b3410fa 100644 --- a/lib/v2/gocn/jobs.js +++ b/lib/v2/gocn/jobs.js @@ -1,23 +1,28 @@ const got = require('@/utils/got'); -const util = require('./util'); +const { parseDate } = require('@/utils/parse-date'); +const { renderHTML } = require('./utils'); module.exports = async (ctx) => { - const base_url = 'https://gocn.vip/topics'; - const api_url = 'https://gocn.vip/apiv3/topic/jobs?currentPage=1&grade=new'; + const api_url = 'https://gocn.vip/api/files?spaceGuid=Gd7OHl¤tPage=1&sort=1'; + const base_url = 'https://gocn.vip/c/3lQ6GbD5ny/s/Gd7OHl'; + const job_url = 'https://gocn.vip/c/3lQ6GbD5ny'; const response = await got({ url: api_url, - headers: { - Referer: base_url, - }, }); - const list = response.data.data.list; + const items = response.data.data.list.map((item) => ({ + title: item.name, + link: `${job_url}/s/${item.spaceGuid}/d/${item.guid}`, + description: renderHTML(JSON.parse(item.content)), + pubDate: parseDate(item.ctime, 'X'), + author: item.nickname, + })); ctx.state.data = { title: `GoCN社区-招聘`, link: base_url, - description: `获取GoCN站点最新招聘`, - item: await Promise.all(list.map((item) => ctx.cache.tryGet(`${base_url}/${item.guid}`, () => util.getFeedItem(item)))), + description: `获取GoCN站点招聘`, + item: items, }; }; diff --git a/lib/v2/gocn/maintainer.js b/lib/v2/gocn/maintainer.js index 37b10046a4a6fb..514f5e5e330bcd 100644 --- a/lib/v2/gocn/maintainer.js +++ b/lib/v2/gocn/maintainer.js @@ -1,4 +1,6 @@ module.exports = { '/': ['AtlanCI', 'CcccFz'], - '/jobs': ['CcccFz'], + '/jobs': ['AtlanCI', 'CcccFz'], + '/news': ['AtlanCI'], + '/topics': ['AtlanCI', 'CcccFz'], }; diff --git a/lib/v2/gocn/news.js b/lib/v2/gocn/news.js new file mode 100644 index 00000000000000..79b0e25ea3a6a3 --- /dev/null +++ b/lib/v2/gocn/news.js @@ -0,0 +1,31 @@ +const got = require('@/utils/got'); +const { parseDate } = require('@/utils/parse-date'); +const { renderHTML } = require('./utils'); + +module.exports = async (ctx) => { + const base_url = 'https://gocn.vip/c/3lQ6GbD5ny/home'; + const article_url = 'https://gocn.vip/c/3lQ6GbD5ny'; + const api_url = 'https://gocn.vip/api/home/page'; + + const response = await got({ + url: api_url, + headers: { + Referer: base_url, + }, + }); + + const items = response.data.data.articlePageList.list.map((item) => ({ + title: item.name, + link: `${article_url}/s/${item.spaceGuid}/d/${item.guid}`, + description: renderHTML(JSON.parse(item.content)), + pubDate: parseDate(item.ctime, 'X'), + author: item.nickname, + })); + + ctx.state.data = { + title: `GoCN社区-最新动态`, + link: base_url, + description: `获取GoCN站点最新动态`, + item: items, + }; +}; diff --git a/lib/v2/gocn/radar.js b/lib/v2/gocn/radar.js index b06f033aa48d9a..3c625d107c6ea3 100644 --- a/lib/v2/gocn/radar.js +++ b/lib/v2/gocn/radar.js @@ -3,10 +3,16 @@ module.exports = { _name: 'GoCN', '.': [ { - title: '文章', + title: '最新动态', docs: 'https://docs.rsshub.app/routes/programming#GoCN', source: ['/'], - target: '/gocn', + target: '/gocn/news', + }, + { + title: '每日新闻', + docs: 'https://docs.rsshub.app/routes/programming#GoCN', + source: ['/'], + target: '/gocn/topics', }, { title: '招聘', diff --git a/lib/v2/gocn/router.js b/lib/v2/gocn/router.js index 3574e546ada605..20228ac683bba5 100644 --- a/lib/v2/gocn/router.js +++ b/lib/v2/gocn/router.js @@ -1,4 +1,6 @@ module.exports = function (router) { - router.get('/', require('./topics')); + router.get('/', require('./news')); router.get('/jobs', require('./jobs')); + router.get('/news', require('./news')); + router.get('/topics', require('./topics')); }; diff --git a/lib/v2/gocn/topics.js b/lib/v2/gocn/topics.js index 713e7b2d28e12b..85d9050d634817 100644 --- a/lib/v2/gocn/topics.js +++ b/lib/v2/gocn/topics.js @@ -1,9 +1,11 @@ const got = require('@/utils/got'); -const util = require('./util'); +const { parseDate } = require('@/utils/parse-date'); +const { renderHTML } = require('./utils'); module.exports = async (ctx) => { - const base_url = 'https://gocn.vip/topics'; - const api_url = 'https://gocn.vip/apiv3/topic/list?currentPage=1&cate2Id=0&grade=new'; + const base_url = 'https://gocn.vip/c/3lQ6GbD5ny/home'; + const article_url = 'https://gocn.vip/c/3lQ6GbD5ny'; + const api_url = 'https://gocn.vip/api/files?spaceGuid=Gd7BTB¤tPage=1&sort=1'; const response = await got({ url: api_url, @@ -12,12 +14,18 @@ module.exports = async (ctx) => { }, }); - const list = response.data.data.list; + const items = response.data.data.list.map((item) => ({ + title: item.name, + link: `${article_url}/s/${item.spaceGuid}/d/${item.guid}`, + description: renderHTML(JSON.parse(item.content)), + pubDate: parseDate(item.ctime, 'X'), + author: item.nickname, + })); ctx.state.data = { - title: `GoCN社区-文章`, + title: `GoCN社区-每日新闻`, link: base_url, - description: `获取GoCN站点最新文章`, - item: await Promise.all(list.map((item) => ctx.cache.tryGet(`${base_url}/${item.guid}`, () => util.getFeedItem(item)))), + description: `获取GoCN站点每日新闻`, + item: items, }; }; diff --git a/lib/v2/gocn/util.js b/lib/v2/gocn/util.js deleted file mode 100644 index 88ed672244d646..00000000000000 --- a/lib/v2/gocn/util.js +++ /dev/null @@ -1,17 +0,0 @@ -const got = require('@/utils/got'); -const { parseDate } = require('@/utils/parse-date'); - -async function getFeedItem(item) { - const response = await got(`https://gocn.vip/apiv3/topic/${item.guid}/info`); - - return { - link: `https://gocn.vip/topics/${item.guid}`, - title: item.title, - description: response.data.data.topic.contentHtml, - pubDate: parseDate(item.ctime, 'X'), - }; -} - -module.exports = { - getFeedItem, -}; diff --git a/lib/v2/gocn/utils.js b/lib/v2/gocn/utils.js new file mode 100644 index 00000000000000..a42d2f83599a07 --- /dev/null +++ b/lib/v2/gocn/utils.js @@ -0,0 +1,38 @@ +const elementMap = { + code_block: (element) => `
${element.children[0].text}
`, + a: (element) => `${renderHTML(element.children)}`, + blockquote: (element) => `
${renderHTML(element.children)}
`, + br: () => '
', + h1: (element) => `

${element.children[0].text}

`, + h2: (element) => `

${element.children[0].text}

`, + h3: (element) => `

${element.children[0].text}

`, + h4: (element) => `

${element.children[0].text}

`, + h5: (element) => `
${element.children[0].text}
`, + h6: (element) => `
${element.children[0].text}
`, + img: (element) => ``, + p: (element) => `

${renderHTML(element.children)}

`, + strong: (element) => `${renderHTML(element.children)}`, + ol: (element) => `
    ${renderHTML(element.children)}
`, + ul: (element) => ``, + li: (element) => `
  • ${renderHTML(element.children)}
  • `, + lic: (element) => element.children[0].text, +}; + +function renderHTML(json) { + return json + .map((element) => { + const handler = elementMap[element.type]; + if (handler) { + return handler(element); + } else if (element.hasOwnProperty('text')) { + return element.text; + } else { + throw new Error(`Unknown handled type: ${element.type}, ${JSON.stringify(element)}`); + } + }) + .join(''); +} + +module.exports = { + renderHTML, +}; diff --git a/website/docs/routes/programming.md b/website/docs/routes/programming.md index f9d3bd88663b8c..e974846c2fc401 100644 --- a/website/docs/routes/programming.md +++ b/website/docs/routes/programming.md @@ -12,51 +12,51 @@ You have the option to utilize the main heading or use individual categories as topics for the path. -| **Code** | _code_ | -|-------------------------|-------------------------| +| **Code** | _code_ | +| --------------------------- | ------------------------- | | **Application Development** | _application-development_ | -| **Browsers** | _browsers_ | -| **CSS** | _css_ | -| **HTML** | _html_ | -| **JavaScript** | _javascript_ | -| **The Server Side** | _the-server-side_ | - -| **Content** | _content_ | -|-------------------------|-------------------------| -| **Community** | _community_ | -| **Content Strategy** | _content-strategy_ | -| **Writing** | _writing_ | - -| **Design** | _design_ | -|-------------------------|-------------------------| -| **Brand Identity** | _brand-identity_ | -| **Graphic Design** | _graphic-design_ | -| **Layout & Grids** | _layout-grids_ | -| **Mobile/Multidevice** | _mobile-multidevice_ | -| **Responsive Design** | _responsive-design_ | +| **Browsers** | _browsers_ | +| **CSS** | _css_ | +| **HTML** | _html_ | +| **JavaScript** | _javascript_ | +| **The Server Side** | _the-server-side_ | + +| **Content** | _content_ | +| -------------------- | ------------------ | +| **Community** | _community_ | +| **Content Strategy** | _content-strategy_ | +| **Writing** | _writing_ | + +| **Design** | _design_ | +| -------------------------- | ---------------------- | +| **Brand Identity** | _brand-identity_ | +| **Graphic Design** | _graphic-design_ | +| **Layout & Grids** | _layout-grids_ | +| **Mobile/Multidevice** | _mobile-multidevice_ | +| **Responsive Design** | _responsive-design_ | | **Typography & Web Fonts** | _typography-web-fonts_ | -| **Industry & Business** | _industry-business_ | -|-------------------------|-------------------------| -| **Business** | _business_ | -| **Career** | _career_ | -| **Industry** | _industry_ | -| **State of the Web** | _state-of-the-web_ | - -| **Process** | _process_ | -|-------------------------|-------------------------| -| **Creativity** | _creativity_ | -| **Project Management** | _project-management_ | -| **Web Strategy** | _web-strategy_ | -| **Workflow & Tools** | _workflow-tools_ | - -| **User Experience** | _user-experience_ | -|-------------------------|-------------------------| -| **Accessibility** | _accessibility_ | +| **Industry & Business** | _industry-business_ | +| ----------------------- | ------------------- | +| **Business** | _business_ | +| **Career** | _career_ | +| **Industry** | _industry_ | +| **State of the Web** | _state-of-the-web_ | + +| **Process** | _process_ | +| ---------------------- | -------------------- | +| **Creativity** | _creativity_ | +| **Project Management** | _project-management_ | +| **Web Strategy** | _web-strategy_ | +| **Workflow & Tools** | _workflow-tools_ | + +| **User Experience** | _user-experience_ | +| ---------------------------- | -------------------------- | +| **Accessibility** | _accessibility_ | | **Information Architecture** | _information-architecture_ | -| **Interaction Design** | _interaction-design_ | -| **Usability** | _usability_ | -| **User Research** | _user-research_ | +| **Interaction Design** | _interaction-design_ | +| **Usability** | _usability_ | +| **User Research** | _user-research_ | @@ -173,7 +173,7 @@ Category | Blog | News | Announcements | Reports | -|------|------|---------------|---------| +| ---- | ---- | ------------- | ------- | | blog | news | announcements | reports | @@ -451,13 +451,18 @@ For instance, the `/github/topics/framework/l=php&o=desc&s=stars` route will gen ## GoCN {#gocn} -### 文章 {#gocn-wen-zhang} +### 最新动态 {#gocn-zui-xin-dong-tai} - + + +### 每日新闻 {#gocn-mei-ri-xin-wen} + + ### 招聘 {#gocn-zhao-pin} - + + ## Hacker News {#hacker-news} @@ -845,41 +850,41 @@ Subscribe to the updates (threads and submission) from a paritcular Hacker News -| **Category** | | -|----------------------|-----------------------| -| Accessibility | accessibility | -| Best practices | best-practices | -| Business | business | -| Career | career | -| Checklists | checklists | -| CSS | css | -| Data Visualization | data-visualization | -| Design | design | -| Design Patterns | design-patterns | -| Design Systems | design-systems | -| E-Commerce | e-commerce | -| Figma | figma | -| Freebies | freebies | -| HTML | html | -| Illustrator | illustrator | -| Inspiration | inspiration | -| JavaScript | javascript | -| Mobile | mobile | -| Performance | performance | -| Privacy | privacy | -| React | react | -| Responsive Design | responsive-design | -| Round-Ups | round-ups | -| SEO | seo | -| Typography | typography | -| Tools | tools | -| UI | ui | -| Usability | usability | -| UX | ux | -| Vue | vue | -| Wallpapers | wallpapers | -| Web Design | web-design | -| Workflow | workflow | +| **Category** | | +| ------------------ | ------------------ | +| Accessibility | accessibility | +| Best practices | best-practices | +| Business | business | +| Career | career | +| Checklists | checklists | +| CSS | css | +| Data Visualization | data-visualization | +| Design | design | +| Design Patterns | design-patterns | +| Design Systems | design-systems | +| E-Commerce | e-commerce | +| Figma | figma | +| Freebies | freebies | +| HTML | html | +| Illustrator | illustrator | +| Inspiration | inspiration | +| JavaScript | javascript | +| Mobile | mobile | +| Performance | performance | +| Privacy | privacy | +| React | react | +| Responsive Design | responsive-design | +| Round-Ups | round-ups | +| SEO | seo | +| Typography | typography | +| Tools | tools | +| UI | ui | +| Usability | usability | +| UX | ux | +| Vue | vue | +| Wallpapers | wallpapers | +| Web Design | web-design | +| Workflow | workflow | @@ -1246,48 +1251,48 @@ Stay up to date on the latest React news, tutorials, resources, and more. Delive -| 分类 | id | -| -------------------- | -- | -| 全部 | | -| Stata 入门 | 16 | -| Stata 教程 | 17 | -| 计量专题 | 18 | -| 内生性 - 因果推断 | 19 | -| 面板数据 | 20 | -| 交乘项 - 调节 - 中介 | 21 | -| 结果输出 | 22 | -| 工具软件 | 23 | -| Stata 绘图 | 24 | -| 数据处理 | 25 | -| Stata 程序 | 26 | -| Probit-Logit | 27 | -| 时间序列 | 28 | -| 空间计量 - 网络分析 | 29 | -| Markdown-LaTeX | 30 | -| 论文写作 | 31 | -| 回归分析 | 32 | -| 其它 | 33 | -| 数据分享 | 34 | -| Stata 资源 | 35 | -| 文本分析 - 爬虫 | 36 | -| Python-R-Matlab | 37 | -| IV-GMM | 38 | -| 倍分法 DID | 39 | -| 断点回归 RDD | 40 | -| PSM-Matching | 41 | -| 合成控制法 | 42 | -| Stata 命令 | 43 | -| 专题课程 | 44 | -| 风险管理 | 45 | -| 生存分析 | 46 | -| 机器学习 | 47 | -| 分位数回归 | 48 | -| SFA-DEA - 效率分析 | 49 | -| 答疑 - 板书 | 50 | -| 论文重现 | 51 | -| 最新课程 | 52 | -| 公开课 | 53 | -| Stata33 讲 | 54 | +| 分类 | id | +| -------------------- | --- | +| 全部 | | +| Stata 入门 | 16 | +| Stata 教程 | 17 | +| 计量专题 | 18 | +| 内生性 - 因果推断 | 19 | +| 面板数据 | 20 | +| 交乘项 - 调节 - 中介 | 21 | +| 结果输出 | 22 | +| 工具软件 | 23 | +| Stata 绘图 | 24 | +| 数据处理 | 25 | +| Stata 程序 | 26 | +| Probit-Logit | 27 | +| 时间序列 | 28 | +| 空间计量 - 网络分析 | 29 | +| Markdown-LaTeX | 30 | +| 论文写作 | 31 | +| 回归分析 | 32 | +| 其它 | 33 | +| 数据分享 | 34 | +| Stata 资源 | 35 | +| 文本分析 - 爬虫 | 36 | +| Python-R-Matlab | 37 | +| IV-GMM | 38 | +| 倍分法 DID | 39 | +| 断点回归 RDD | 40 | +| PSM-Matching | 41 | +| 合成控制法 | 42 | +| Stata 命令 | 43 | +| 专题课程 | 44 | +| 风险管理 | 45 | +| 生存分析 | 46 | +| 机器学习 | 47 | +| 分位数回归 | 48 | +| SFA-DEA - 效率分析 | 49 | +| 答疑 - 板书 | 50 | +| 论文重现 | 51 | +| 最新课程 | 52 | +| 公开课 | 53 | +| Stata33 讲 | 54 |