diff --git a/docs/programming.md b/docs/programming.md index 3c5865f74..69ac0ee26 100644 --- a/docs/programming.md +++ b/docs/programming.md @@ -559,6 +559,24 @@ GitHub 官方也提供了一些 RSS: +## ModelScope 魔搭社区 + +### 数据集 + + + +### 模型库 + + + +### 创空间 + + + +### DevPress 官方社区 + + + ## MySQL ### Release Notes diff --git a/lib/v2/modelscope/community.js b/lib/v2/modelscope/community.js new file mode 100644 index 000000000..57f2eee04 --- /dev/null +++ b/lib/v2/modelscope/community.js @@ -0,0 +1,55 @@ +const cheerio = require('cheerio'); +const got = require('@/utils/got'); +const path = require('path'); +const timezone = require('@/utils/timezone'); +const { art } = require('@/utils/render'); +const { parseDate } = require('@/utils/parse-date'); + +module.exports = async (ctx) => { + const baseUrl = 'https://community.modelscope.cn'; + + const { data } = await got.post(`${baseUrl}/v1/namespace_page/article`, { + json: { id: 142373, notInMediaAidList: [], pageNum: 1, pageSize: ctx.query.limit ? parseInt(ctx.query.limit) : 30 }, + }); + + const articles = data.data.content.map((c) => ({ + title: c.content.name, + description: c.content.desc, + author: c.nickname, + link: `${baseUrl}/${c.content.id}.html`, + pubDate: timezone(parseDate(c.content.createdTime), 8), + category: c.content.externalData.tags.map((t) => t.name), + thumb: c.content.thumb, + })); + + const items = await Promise.all( + articles.map((item) => + ctx.cache.tryGet(item.link, async () => { + const { data } = await got(item.link); + + const $ = cheerio.load(data); + const initialData = JSON.parse( + $('script') + .text() + .match(/window\.__INITIAL_STATE__\s*=\s*({.*?});/)[1] + ); + + item.description = art(path.join(__dirname, 'templates/community.art'), { + thumb: item.thumb, + quote: item.description, + content: initialData.pageData.detail.ext.content, + }); + + return item; + }) + ) + ); + + ctx.state.data = { + title: 'ModelScope魔搭社区-DevPress官方社区', + description: 'ModelScope魔搭社区 DevPress官方社区-ModelScope旨在打造下一代开源的模型即服务共享平台,为泛AI开发者提供灵活、易用、低成本的一站式模型服务产品,让模型应用更简单。', + image: 'https://g.alicdn.com/sail-web/maas/0.8.10/favicon/128.ico', + link: baseUrl, + item: items, + }; +}; diff --git a/lib/v2/modelscope/datasets.js b/lib/v2/modelscope/datasets.js new file mode 100644 index 000000000..7293ad2bd --- /dev/null +++ b/lib/v2/modelscope/datasets.js @@ -0,0 +1,55 @@ +const got = require('@/utils/got'); +const md = require('markdown-it')({ + html: true, + linkify: true, +}); +const path = require('path'); +const { art } = require('@/utils/render'); +const { parseDate } = require('@/utils/parse-date'); + +module.exports = async (ctx) => { + const baseUrl = 'https://modelscope.cn'; + const link = `${baseUrl}/datasets`; + + const { data } = await got(`${baseUrl}/api/v1/dolphin/datasets`, { + searchParams: { + PageSize: ctx.query.limit ? parseInt(ctx.query.limit) : 36, + PageNumber: 1, + Target: '', + Sort: 'gmt_modified', + }, + }); + + const datasets = data.Data.map((dataset) => ({ + title: dataset.ChineseName, + description: dataset.Description, + author: dataset.CreatedBy, + link: `${link}/${dataset.Namespace}/${dataset.Name}`, + pubDate: parseDate(dataset.GmtCreate, 'X'), + category: dataset.UserDefineTags.split(','), + slug: `/${dataset.Namespace}/${dataset.Name}`, + })); + + const items = await Promise.all( + datasets.map((item) => + ctx.cache.tryGet(item.link, async () => { + const { data } = await got(`${baseUrl}/api/v1/datasets${item.slug}`); + + const content = data.Data.ReadmeContent.replace(/img src="(?!http)(.*?)"/g, `img src="${baseUrl}/api/v1/datasets${item.slug}/repo?Revision=master&FilePath=$1&View=true"`); + item.description = art(path.join(__dirname, 'templates/desc.art'), { + description: item.description, + md: md.render(content), + }); + return item; + }) + ) + ); + + ctx.state.data = { + title: '数据集首页 · 魔搭社区', + description: 'ModelScope——汇聚各领域先进的机器学习模型,提供模型探索体验、推理、训练、部署和应用的一站式服务。在这里,共建模型开源社区,发现、学习、定制和分享心仪的模型。', + image: 'https://g.alicdn.com/sail-web/maas/0.8.10/favicon/128.ico', + link, + item: items, + }; +}; diff --git a/lib/v2/modelscope/maintainer.js b/lib/v2/modelscope/maintainer.js new file mode 100644 index 000000000..c2e6add99 --- /dev/null +++ b/lib/v2/modelscope/maintainer.js @@ -0,0 +1,6 @@ +module.exports = { + '/community': ['TonyRL'], + '/datasets': ['TonyRL'], + '/models': ['TonyRL'], + '/studios': ['TonyRL'], +}; diff --git a/lib/v2/modelscope/models.js b/lib/v2/modelscope/models.js new file mode 100644 index 000000000..1b95ce3fe --- /dev/null +++ b/lib/v2/modelscope/models.js @@ -0,0 +1,45 @@ +const got = require('@/utils/got'); +const md = require('markdown-it')({ + html: true, + linkify: true, +}); +const { parseDate } = require('@/utils/parse-date'); + +module.exports = async (ctx) => { + const baseUrl = 'https://modelscope.cn'; + const link = `${baseUrl}/models`; + + const { data } = await got.put(`${baseUrl}/api/v1/dolphin/models`, { + json: { PageSize: ctx.query.limit ? parseInt(ctx.query.limit) : 36, PageNumber: 1, SortBy: 'GmtModified', Target: '', SingleCriterion: [] }, + }); + + const models = data.Data.Model.Models.map((model) => ({ + title: model.ChineseName, + description: model.Description, + author: model.Organization.FullName, + link: `${link}/${model.Path}/${model.Name}`, + pubDate: parseDate(model.CreatedTime, 'X'), + category: [...new Set([...model.Tasks.map((task) => task.ChineseName), ...model.Tags])], + slug: `/${model.Path}/${model.Name}`, + })); + + const items = await Promise.all( + models.map((item) => + ctx.cache.tryGet(item.link, async () => { + const { data } = await got(`${baseUrl}/api/v1/models${item.slug}`); + + const content = data.Data.ReadMeContent.replace(/img src="(?!http)(.*?)"/g, `img src="${baseUrl}/api/v1/models${item.slug}/repo?Revision=master&FilePath=$1&View=true"`); + item.description = md.render(content); + return item; + }) + ) + ); + + ctx.state.data = { + title: '模型库首页 · 魔搭社区', + description: 'ModelScope——汇聚各领域先进的机器学习模型,提供模型探索体验、推理、训练、部署和应用的一站式服务。在这里,共建模型开源社区,发现、学习、定制和分享心仪的模型。', + image: 'https://g.alicdn.com/sail-web/maas/0.8.10/favicon/128.ico', + link, + item: items, + }; +}; diff --git a/lib/v2/modelscope/radar.js b/lib/v2/modelscope/radar.js new file mode 100644 index 000000000..3167a3b5c --- /dev/null +++ b/lib/v2/modelscope/radar.js @@ -0,0 +1,33 @@ +module.exports = { + 'modelscope.cn': { + _name: 'ModelScope 魔搭社区', + '.': [ + { + title: '数据集', + docs: 'https://docs.rsshub.app/programming.html#modelscope-mo-da-she-qu', + source: ['/datasets'], + target: '/modelscope/datasets', + }, + { + title: '模型库', + docs: 'https://docs.rsshub.app/programming.html#modelscope-mo-da-she-qu', + source: ['/models'], + target: '/modelscope/models', + }, + { + title: '创空间', + docs: 'https://docs.rsshub.app/programming.html#modelscope-mo-da-she-qu', + source: ['/studios'], + target: '/modelscope/studios', + }, + ], + community: [ + { + title: 'DevPress 官方社区', + docs: 'https://docs.rsshub.app/programming.html#modelscope-mo-da-she-qu', + source: ['/'], + target: '/modelscope/community', + }, + ], + }, +}; diff --git a/lib/v2/modelscope/router.js b/lib/v2/modelscope/router.js new file mode 100644 index 000000000..889d162a1 --- /dev/null +++ b/lib/v2/modelscope/router.js @@ -0,0 +1,6 @@ +module.exports = (router) => { + router.get('/community', require('./community')); + router.get('/datasets', require('./datasets')); + router.get('/models', require('./models')); + router.get('/studios', require('./studios')); +}; diff --git a/lib/v2/modelscope/studios.js b/lib/v2/modelscope/studios.js new file mode 100644 index 000000000..ac9e67c81 --- /dev/null +++ b/lib/v2/modelscope/studios.js @@ -0,0 +1,57 @@ +const got = require('@/utils/got'); +const md = require('markdown-it')({ + html: true, + linkify: true, +}); +const path = require('path'); +const { art } = require('@/utils/render'); +const { parseDate } = require('@/utils/parse-date'); + +module.exports = async (ctx) => { + const baseUrl = 'https://modelscope.cn'; + const link = `${baseUrl}/studios`; + + const { data } = await got.put(`${baseUrl}/api/v1/studios`, { + json: { + PageSize: ctx.query.limit ? parseInt(ctx.query.limit) : 36, + PageNumber: 1, + SortBy: 'gmt_modified', + }, + }); + + const studios = data.Data.Studios.map((studio) => ({ + title: studio.ChineseName || studio.Name, + description: studio.Description, + author: studio.CreatedBy, + link: `${link}/${studio.Path}/${studio.Name}`, + pubDate: parseDate(studio.CreatedTime, 'X'), + category: studio.Tags, + slug: `/${studio.Path}/${studio.Name}`, + coverImage: studio.CoverImage.startsWith('https://img.alicdn.com/') ? undefined : studio.CoverImage, + })); + + const items = await Promise.all( + studios.map((item) => + ctx.cache.tryGet(item.link, async () => { + const { data } = await got(`${baseUrl}/api/v1/studio${item.slug}`); + + const content = data.Data.ReadMeContent; + item.description = art(path.join(__dirname, 'templates/desc.art'), { + coverImage: item.coverImage, + description: item.description, + md: md.render(content), + }); + + return item; + }) + ) + ); + + ctx.state.data = { + title: '创空间首页 · 魔搭社区', + description: 'ModelScope——汇聚各领域先进的机器学习模型,提供模型探索体验、推理、训练、部署和应用的一站式服务。在这里,共建模型开源社区,发现、学习、定制和分享心仪的模型。', + image: 'https://g.alicdn.com/sail-web/maas/0.8.10/favicon/128.ico', + link, + item: items, + }; +}; diff --git a/lib/v2/modelscope/templates/community.art b/lib/v2/modelscope/templates/community.art new file mode 100644 index 000000000..7dafedaa7 --- /dev/null +++ b/lib/v2/modelscope/templates/community.art @@ -0,0 +1,11 @@ +{{ if thumb }} +
+{{ /if }} + +{{ if quote }} +
{{ quote }}
+{{ /if }} + +{{ if content }} + {{@ content }} +{{ /if }} diff --git a/lib/v2/modelscope/templates/desc.art b/lib/v2/modelscope/templates/desc.art new file mode 100644 index 000000000..5a0d9d950 --- /dev/null +++ b/lib/v2/modelscope/templates/desc.art @@ -0,0 +1,9 @@ +{{ if coverImage }} +
+{{ /if }} + +{{ if description }} + {{ description }}
+{{ /if }} + +{{@ md }}