mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-09 14:40:23 +08:00
feat(route): add dockerhub image new tag (#8965)
* feat: /dockerhub/tags/:owner/:image fix #6916 * fix: update the doc link of /dockerhub/build * docs(en): /dockerhub/tag/:owner/:image * docs: fix typo * fix(dockerhub/tags): use parseDate() * docs: link docs to h2 instead of h3 * chore: move /dockerhub/build to v2 * docs: put warning inside <Route> * fix(dockerhub): use docker.com/hub as the radar path * fix(dockerhub/tag): add :limits? * feat(dockerhub): polish the GUID * fix(dockerhub/tag): stricter argument checks * fix(dockerhub/tag): handle NaN per Deepscan CI
This commit is contained in:
@@ -312,17 +312,6 @@
|
||||
},
|
||||
'wineyun.com': { _name: '酒云网', www: [{ title: '最新商品', docs: 'https://docs.rsshub.app/other.html#jiu-yun-wang', source: ['/:category'], target: '/wineyun/:category' }] },
|
||||
'epicgames.com': { _name: 'Epic Games', www: [{ title: '每周免费游戏', docs: 'https://docs.rsshub.app/game.html#epicgames-freegame', source: '/store/zh-CN/free-games', target: '/epicgames/freegames' }] },
|
||||
'docker.com': {
|
||||
_name: 'Docker',
|
||||
hub: [
|
||||
{
|
||||
title: '镜像有新 Build',
|
||||
docs: 'https://docs.rsshub.app/program-update.html#docker-hub',
|
||||
source: ['/r/:owner/:image', '/r/:owner/:image/tags', '/_/:image'],
|
||||
target: (params) => `/dockerhub/build/${params.owner ? params.owner : 'library'}/${params.image}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
'nga.cn': {
|
||||
_name: 'NGA',
|
||||
bbs: [
|
||||
|
||||
@@ -112,7 +112,7 @@ For example: `https://www.curseforge.com/sc2/assets/taylor-mouses-stuff/files` t
|
||||
|
||||
### Image New Build
|
||||
|
||||
<RouteEn author="HenryQW" example="/dockerhub/build/wangqiru/ttrss" path="/dockerhub/build/:owner/:image/:tag?" :paramsDesc="['Image owner', 'Image name', 'Image tag,default to latest']"/>
|
||||
<RouteEn author="HenryQW" example="/dockerhub/build/wangqiru/ttrss" path="/dockerhub/build/:owner/:image/:tag?" :paramsDesc="['Image owner', 'Image name', 'Image tag,default to latest']">
|
||||
|
||||
::: warning
|
||||
|
||||
@@ -120,6 +120,20 @@ The owner of the official image fills in the library, for example: https://rsshu
|
||||
|
||||
:::
|
||||
|
||||
</RouteEn>
|
||||
|
||||
### Image New Tag
|
||||
|
||||
<RouteEn author="outloudvi" example="/dockerhub/tag/library/mariadb" path="/dockerhub/tag/:owner/:image/:limits?" :paramsDesc="['Image owner', 'Image name', 'Tag count, 10 by default']">
|
||||
|
||||
::: warning
|
||||
|
||||
Use `library` as the `owner` for official images, such as <https://rsshub.app/dockerhub/tag/library/mysql>
|
||||
|
||||
:::
|
||||
|
||||
</RouteEn>
|
||||
|
||||
## Eagle
|
||||
|
||||
### Changelog
|
||||
|
||||
@@ -150,7 +150,7 @@ pageClass: routes
|
||||
|
||||
### 镜像有新 Build
|
||||
|
||||
<Route author="HenryQW" example="/dockerhub/build/wangqiru/ttrss" path="/dockerhub/build/:owner/:image/:tag?" :paramsDesc="['镜像作者', '镜像名称', '镜像标签,默认 latest']" radar="1" rssbud="1"/>
|
||||
<Route author="HenryQW" example="/dockerhub/build/wangqiru/ttrss" path="/dockerhub/build/:owner/:image/:tag?" :paramsDesc="['镜像作者', '镜像名称', '镜像标签,默认 latest']" radar="1" rssbud="1">
|
||||
|
||||
::: warning 注意
|
||||
|
||||
@@ -158,6 +158,20 @@ pageClass: routes
|
||||
|
||||
:::
|
||||
|
||||
</Route>
|
||||
|
||||
### 镜像有新 Tag
|
||||
|
||||
<Route author="outloudvi" example="/dockerhub/tag/library/mariadb" path="/dockerhub/tag/:owner/:image/:limits?" :paramsDesc="['镜像作者', '镜像名称', 'tag 数量,默认为 10']" radar="1" rssbud="1">
|
||||
|
||||
::: warning 注意
|
||||
|
||||
官方镜像的 owner 填写 library, 如: <https://rsshub.app/dockerhub/tag/library/mysql>
|
||||
|
||||
:::
|
||||
|
||||
</Route>
|
||||
|
||||
## Eagle
|
||||
|
||||
### 更新日志
|
||||
|
||||
@@ -786,17 +786,6 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
'docker.com': {
|
||||
_name: 'Docker',
|
||||
hub: [
|
||||
{
|
||||
title: '镜像有新 Build',
|
||||
docs: 'https://docs.rsshub.app/program-update.html#docker-hub',
|
||||
source: ['/r/:owner/:image', '/r/:owner/:image/tags', '/_/:image'],
|
||||
target: (params) => `/dockerhub/build/${params.owner ? params.owner : 'library'}/${params.image}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
'nga.cn': {
|
||||
_name: 'NGA',
|
||||
bbs: [
|
||||
|
||||
@@ -1376,9 +1376,6 @@ router.get('/meipai/user/:uid', lazyloadRouteHandler('./routes/meipai/user'));
|
||||
// 多知网
|
||||
router.get('/duozhi', lazyloadRouteHandler('./routes/duozhi'));
|
||||
|
||||
// Docker Hub
|
||||
router.get('/dockerhub/build/:owner/:image/:tag?', lazyloadRouteHandler('./routes/dockerhub/build'));
|
||||
|
||||
// 人人都是产品经理
|
||||
router.get('/woshipm/popular', lazyloadRouteHandler('./routes/woshipm/popular'));
|
||||
router.get('/woshipm/wen', lazyloadRouteHandler('./routes/woshipm/wen'));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const got = require('@/utils/got');
|
||||
const { hash } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { owner, image, tag = 'latest' } = ctx.params;
|
||||
@@ -22,7 +23,8 @@ module.exports = async (ctx) => {
|
||||
link: `https://hub.docker.com/layers/docker/${namespace}/${tag}/images/${item.images[0].digest.replace(':', '-')}`,
|
||||
author: owner,
|
||||
pubDate: new Date(item.last_updated).toUTCString(),
|
||||
guid: item.last_updated,
|
||||
// only check for different images hashes (considering varients of all arches), since the tag name is already fixed
|
||||
guid: hash(item.images),
|
||||
},
|
||||
],
|
||||
};
|
||||
4
lib/v2/dockerhub/maintainer.js
Normal file
4
lib/v2/dockerhub/maintainer.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
'/build/:owner/:image/:tag?': ['HenryQW'],
|
||||
'/tag/:owner/:image': ['outloudvi'],
|
||||
};
|
||||
19
lib/v2/dockerhub/radar.js
Normal file
19
lib/v2/dockerhub/radar.js
Normal file
@@ -0,0 +1,19 @@
|
||||
module.exports = {
|
||||
'docker.com': {
|
||||
_name: 'Docker Hub',
|
||||
hub: [
|
||||
{
|
||||
title: '镜像有新 Build',
|
||||
docs: 'https://docs.rsshub.app/program-update.html#docker-hub',
|
||||
source: ['/r/:owner/:image', '/r/:owner/:image/tags', '/_/:image'],
|
||||
target: (params) => `/dockerhub/build/${params.owner ? params.owner : 'library'}/${params.image}`,
|
||||
},
|
||||
{
|
||||
title: '镜像有新 Tag',
|
||||
docs: 'https://docs.rsshub.app/program-update.html#docker-hub',
|
||||
source: ['/r/:owner/:image', '/r/:owner/:image/tags', '/_/:image'],
|
||||
target: (params) => `/dockerhub/tag/${params.owner ? params.owner : 'library'}/${params.image}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
4
lib/v2/dockerhub/router.js
Normal file
4
lib/v2/dockerhub/router.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = function (router) {
|
||||
router.get('/build/:owner/:image/:tag?', require('./build'));
|
||||
router.get('/tag/:owner/:image/:limits?', require('./tag'));
|
||||
};
|
||||
33
lib/v2/dockerhub/tag.js
Normal file
33
lib/v2/dockerhub/tag.js
Normal file
@@ -0,0 +1,33 @@
|
||||
const got = require('@/utils/got');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const { hash } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { owner, image, limits } = ctx.params;
|
||||
|
||||
const namespace = `${owner}/${image}`;
|
||||
const link = `https://hub.docker.com/r/${namespace}`;
|
||||
|
||||
const pageSize = !isNaN(parseInt(limits)) ? parseInt(limits) : 10;
|
||||
|
||||
const data = await got.get(`https://hub.docker.com/v2/repositories/${namespace}/tags/?page_size=${pageSize}`);
|
||||
const metadata = await got.get(`https://hub.docker.com/v2/repositories/${namespace}/`);
|
||||
|
||||
const tags = data.data.results;
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${namespace} tags`,
|
||||
description: metadata.data.description,
|
||||
link,
|
||||
language: 'en',
|
||||
item: tags.map((item) => ({
|
||||
title: `${namespace}:${item.name} was updated`,
|
||||
description: `${namespace}:${item.name} was updated, supporting the architectures of ${item.images.map((img) => `${img.os}/${img.architecture}`).join(', ')}`,
|
||||
link: `https://hub.docker.com/layers/${owner === 'library' ? `${image}/` : ''}${namespace}/${item.name}/images/${item.images[0].digest.replace(':', '-')}`,
|
||||
author: owner,
|
||||
pubDate: parseDate(item.tag_last_pushed),
|
||||
// check for (1) different tag names and (2) different image hashes, considering varients of all arches
|
||||
guid: `${namespace}:${item.name}@${hash(item.images)}`,
|
||||
})),
|
||||
};
|
||||
};
|
||||
10
lib/v2/dockerhub/utils.js
Normal file
10
lib/v2/dockerhub/utils.js
Normal file
@@ -0,0 +1,10 @@
|
||||
const md5 = require('@/utils/md5');
|
||||
|
||||
function hash(images) {
|
||||
const entries = Object.entries(images)
|
||||
.map((x) => [`${x.os}/${x.architecture}`, x.digest])
|
||||
.sort((a, b) => a[0] - b[0]);
|
||||
return md5(entries.map((x) => x.join(',')).join('|'));
|
||||
}
|
||||
|
||||
module.exports = { hash };
|
||||
Reference in New Issue
Block a user