From a1abbfc1ab37a59d248d7fd69ecae2664603da1d Mon Sep 17 00:00:00 2001 From: CaoMeiYouRen <40430746+CaoMeiYouRen@users.noreply.github.com> Date: Sun, 23 Jun 2024 13:24:48 +0800 Subject: [PATCH] feat(route): add Alpine Linux packages update route (#15969) * feat(route): add Alpine Linux packages update route * fix(route): fix alpinelinux issues * fix(route): fix alpinelinux route guid --- lib/routes/alpinelinux/namespace.ts | 11 +++ lib/routes/alpinelinux/pkgs.ts | 102 ++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 lib/routes/alpinelinux/namespace.ts create mode 100644 lib/routes/alpinelinux/pkgs.ts diff --git a/lib/routes/alpinelinux/namespace.ts b/lib/routes/alpinelinux/namespace.ts new file mode 100644 index 000000000..e7dfedfe9 --- /dev/null +++ b/lib/routes/alpinelinux/namespace.ts @@ -0,0 +1,11 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: 'Alpine Linux', + url: 'alpinelinux.org', + description: 'Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox.', + zh: { + name: 'Alpine Linux', + description: 'Alpine Linux 是一个基于 musl libc 和 busybox 的面向安全的轻量级 Linux 发行版。', + }, +}; diff --git a/lib/routes/alpinelinux/pkgs.ts b/lib/routes/alpinelinux/pkgs.ts new file mode 100644 index 000000000..9237f679c --- /dev/null +++ b/lib/routes/alpinelinux/pkgs.ts @@ -0,0 +1,102 @@ +import { Data, Route } from '@/types'; +import { load } from 'cheerio'; +import cache from '@/utils/cache'; +import { Context } from 'hono'; +import got from '@/utils/got'; +import { parseDate } from '@/utils/parse-date'; +import { config } from '@/config'; + +export const route: Route = { + name: 'Packages', + categories: ['program-update'], + maintainers: ['CaoMeiYouRen'], + path: '/pkgs/:name/:routeParams?', + parameters: { name: 'Packages name', routeParams: 'Filters of packages type. E.g. branch=edge&repo=main&arch=armv7&maintainer=Jakub%20Jirutka' }, + example: '/alpinelinux/pkgs/nodejs', + description: `Alpine Linux packages update`, + handler, + radar: [ + { + source: ['https://pkgs.alpinelinux.org/packages'], + target: (params, url) => { + const searchParams = new URL(url).searchParams; + const name = searchParams.get('name'); + searchParams.delete('name'); + const routeParams = searchParams.toString(); + return `/alpinelinux/pkgs/${name}/${routeParams}`; + }, + }, + ], + zh: { + name: '软件包', + description: 'Alpine Linux 软件包更新', + }, +}; + +type RowData = { + package: string; + packageUrl?: string; + version: string; + project?: string; + license: string; + branch: string; + repository: string; + architecture: string; + maintainer: string; + buildDate: string; +}; + +function parseTableToJSON(tableHTML: string) { + const $ = load(tableHTML); + const data: RowData[] = $('tbody tr') + .toArray() + .map((row) => ({ + package: $(row).find('.package a').text().trim(), + packageUrl: $(row).find('.package a').attr('href')?.trim(), + version: $(row).find('.version a').text().trim(), + project: $(row).find('.url a').attr('href')?.trim(), + license: $(row).find('.license').text().trim(), + branch: $(row).find('.branch').text().trim(), + repository: $(row).find('.repo a').text().trim(), + architecture: $(row).find('.arch a').text().trim(), + maintainer: $(row).find('.maintainer a').text().trim(), + buildDate: $(row).find('.bdate').text().trim(), + })); + + return data; +} + +async function handler(ctx: Context): Promise { + const { name, routeParams } = ctx.req.param(); + const query = new URLSearchParams(routeParams); + query.append('name', name); + const link = `https://pkgs.alpinelinux.org/packages?${query.toString()}`; + const key = `alpinelinux:${query.toString()}`; + const rowData = (await cache.tryGet( + key, + async () => { + const response = await got({ + url: link, + }); + const html = response.data; + return parseTableToJSON(html); + }, + config.cache.routeExpire, + false + )) as RowData[]; + + const items = rowData.map((e) => ({ + title: `${e.package}@${e.version}/${e.architecture}`, + description: `Version: ${e.version}
Project: ${e.project}
License: ${e.license}
Branch: ${e.branch}
Repository: ${e.repository}
Maintainer: ${e.maintainer}
Build Date: ${e.buildDate}`, + link: e.packageUrl, + guid: `${e.packageUrl}#${e.version}`, + author: e.maintainer, + pubDate: parseDate(e.buildDate), + })); + return { + title: `${name} - Alpine Linux packages`, + link, + description: 'Alpine Linux packages update', + item: items, + }; +}