Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
TonyRL authored Nov 5, 2024
2 parents d1fff12 + ee2f07d commit d44cd0e
Show file tree
Hide file tree
Showing 58 changed files with 1,832 additions and 468 deletions.
25 changes: 0 additions & 25 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,6 @@ permissions:
checks: write

jobs:
fix-pnpm-lock:
# workaround for https://github.com/dependabot/dependabot-core/issues/7258
# until https://github.com/pnpm/pnpm/issues/6530 is fixed
if: github.triggering_actor == 'dependabot[bot]' && github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: 'pnpm'
- run: |
rm pnpm-lock.yaml
pnpm i
- uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: 'chore: fix pnpm install'
commit_user_name: dependabot[bot]
commit_user_email: 49699333+dependabot[bot]@users.noreply.github.com
commit_author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

vitest:
runs-on: ubuntu-latest
timeout-minutes: 10
Expand Down
39 changes: 16 additions & 23 deletions lib/api/category/one.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ for (const namespace in namespaces) {
}
}

const ParamsSchema = z.object({
category: z.string().openapi({
param: {
name: 'category',
in: 'path',
},
example: 'popular',
}),
});

const QuerySchema = z.object({
categories: z
.string()
Expand All @@ -36,20 +46,11 @@ const route = createRoute({
tags: ['Category'],
request: {
query: QuerySchema,
params: z.object({
category: z.string(),
}),
params: ParamsSchema,
},
responses: {
200: {
description: 'Namespace list by categories',
content: {
'application/json': {
schema: z.object({
data: z.record(z.string(), z.any()),
}),
},
},
description: 'Namespace list by categories and language',
},
},
});
Expand All @@ -66,23 +67,15 @@ const handler: RouteHandler<typeof route> = (ctx) => {
// Get namespaces that exist in all requested categories
const commonNamespaces = Object.keys(categoryList[category] || {}).filter((namespace) => allCategories.every((cat) => categoryList[cat]?.[namespace]));

// Create result using the path category as key
let result = {
[category]: Object.fromEntries(commonNamespaces.map((namespace) => [namespace, categoryList[category][namespace]])),
};
// Create result directly from common namespaces
let result = Object.fromEntries(commonNamespaces.map((namespace) => [namespace, categoryList[category][namespace]]));

// Filter by language if provided
if (lang) {
result = Object.fromEntries(
Object.entries(result)
.map(([cat, namespaces]) => [cat, Object.fromEntries(Object.entries(namespaces).filter(([, value]) => value.lang === lang))])
.filter(([, namespaces]) => Object.keys(namespaces).length > 0)
);
result = Object.fromEntries(Object.entries(result).filter(([, value]) => value.lang === lang));
}

return ctx.json({
data: result,
});
return ctx.json(result);
};

export { route, handler };
19 changes: 19 additions & 0 deletions lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ export type Config = {
bupt: {
portal_cookie?: string;
};
caixin: {
cookie?: string;
};
civitai: {
cookie?: string;
};
Expand Down Expand Up @@ -293,6 +296,14 @@ export type Config = {
telegram: {
token?: string;
session?: string;
apiId?: number;
apiHash?: string;
maxConcurrentDownloads?: number;
proxy?: {
host?: string;
port?: number;
secret?: string;
};
};
tophub: {
cookie?: string;
Expand Down Expand Up @@ -500,6 +511,9 @@ const calculateValue = () => {
bupt: {
portal_cookie: envs.BUPT_PORTAL_COOKIE,
},
caixin: {
cookie: envs.CAIXIN_COOKIE,
},
civitai: {
cookie: envs.CIVITAI_COOKIE,
},
Expand Down Expand Up @@ -703,6 +717,11 @@ const calculateValue = () => {
apiId: envs.TELEGRAM_API_ID,
apiHash: envs.TELEGRAM_API_HASH,
maxConcurrentDownloads: envs.TELEGRAM_MAX_CONCURRENT_DOWNLOADS,
proxy: {
host: envs.TELEGRAM_PROXY_HOST,
port: envs.TELEGRAM_PROXY_PORT,
secret: envs.TELEGRAM_PROXY_SECRET,
},
},
tophub: {
cookie: envs.TOPHUB_COOKIE,
Expand Down
19 changes: 10 additions & 9 deletions lib/routes/abc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { getCurrentPath } from '@/utils/helpers';
const __dirname = getCurrentPath(import.meta.url);

import cache from '@/utils/cache';
import got from '@/utils/got';
import ofetch from '@/utils/ofetch';
import { load } from 'cheerio';
import { parseDate } from '@/utils/parse-date';
import { art } from '@/utils/render';
import path from 'node:path';

export const route: Route = {
path: '/:category{.+}?',
example: '/wa',
radar: [
{
source: ['abc.net.au/:category*'],
Expand All @@ -30,7 +31,7 @@ export const route: Route = {
The supported channels are all listed in the table below. For other channels, please find the \`documentId\` in the source code of the channel page and fill it in as above.
:::`,
maintainers: ['nczitzk'],
maintainers: ['nczitzk', 'pseudoyu'],
handler,
};

Expand All @@ -50,18 +51,18 @@ async function handler(ctx) {
documentId = category;
const feedUrl = new URL(`news/feed/${documentId}/rss.xml`, rootUrl).href;

const { data: feedResponse } = await got(feedUrl);
const feedResponse = await ofetch(feedUrl);
currentUrl = feedResponse.match(/<link>([\w-./:?]+)<\/link>/)[1];
}

const { data: currentResponse } = await got(currentUrl);
const currentResponse = await ofetch(currentUrl);

const $ = load(currentResponse);

documentId = documentId ?? $('div[data-uri^="coremedia://collection/"]').first().prop('data-uri').split(/\//).pop();

const { data: response } = await got(apiUrl, {
searchParams: {
const response = await ofetch(apiUrl, {
query: {
name: 'PaginationArticles',
documentId,
size: limit,
Expand All @@ -71,7 +72,7 @@ async function handler(ctx) {
let items = response.collection.slice(0, limit).map((i) => {
const item = {
title: i.title.children ?? i.title,
link: new URL(i.link.to, rootUrl).href,
link: i.link.startsWith('https://') ? i.link : new URL(i.link, rootUrl).href,
description: art(path.join(__dirname, 'templates/description.art'), {
image: i.image
? {
Expand Down Expand Up @@ -99,7 +100,7 @@ async function handler(ctx) {
items.map((item) =>
cache.tryGet(item.link, async () => {
try {
const { data: detailResponse } = await got(item.link);
const detailResponse = await ofetch(item.link);

const content = load(detailResponse);

Expand Down Expand Up @@ -173,7 +174,7 @@ async function handler(ctx) {
)
);

const icon = new URL($('link[rel="apple-touch-icon"]').prop('href'), rootUrl).href;
const icon = new URL($('link[rel="apple-touch-icon"]').prop('href') || '', rootUrl).href;

return {
item: items,
Expand Down
4 changes: 2 additions & 2 deletions lib/routes/alpinelinux/pkgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function parseTableToJSON(tableHTML: string) {
package: $(row).find('.package a').text().trim(),
packageUrl: $(row).find('.package a').attr('href')?.trim(),
description: $(row).find('.package a').attr('aria-label')?.trim(),
version: $(row).find('.version a').text().trim(),
version: $(row).find('.version').text().trim(),
project: $(row).find('.url a').attr('href')?.trim(),
license: $(row).find('.license').text().trim(),
branch: $(row).find('.branch').text().trim(),
Expand All @@ -73,7 +73,7 @@ async function handler(ctx: Context): Promise<Data> {
const query = new URLSearchParams(routeParams);
query.append('name', name);
const link = `https://pkgs.alpinelinux.org/packages?${query.toString()}`;
const key = `alpinelinux:${query.toString()}`;
const key = `alpinelinux:packages:${query.toString()}`;
const rowData = (await cache.tryGet(
key,
async () => {
Expand Down
2 changes: 1 addition & 1 deletion lib/routes/anime1/anime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async function handler(ctx) {

const $ = load(response);

const title = $('page-title').text().trim();
const title = $('.page-title').text().trim();

const items = $('article')
.toArray()
Expand Down
57 changes: 57 additions & 0 deletions lib/routes/baoyu/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Route, DataItem } from '@/types';
import got from '@/utils/got';
import { load } from 'cheerio';
import { parseDate } from '@/utils/parse-date';
import parser from '@/utils/rss-parser';
import cache from '@/utils/cache';

export const route: Route = {
path: '/blog',
categories: ['blog'],
example: '/baoyu/blog',
radar: [
{
source: ['baoyu.io/'],
},
],
url: 'baoyu.io/',
name: 'Blog',
maintainers: ['liyaozhong'],
handler,
description: '宝玉 - 博客文章',
};

async function handler() {
const rootUrl = 'https://baoyu.io';
const feedUrl = `${rootUrl}/feed.xml`;

const feed = await parser.parseURL(feedUrl);

const items = await Promise.all(
feed.items.map((item) => {
const link = item.link;

return cache.tryGet(link as string, async () => {
const response = await got(link);
const $ = load(response.data);

const container = $('.container');
const content = container.find('.prose').html() || '';

return {
title: item.title,
description: content,
link,
pubDate: item.pubDate ? parseDate(item.pubDate) : undefined,
author: item.creator || '宝玉',
} as DataItem;
});
})
);

return {
title: '宝玉的博客',
link: rootUrl,
item: items,
};
}
8 changes: 8 additions & 0 deletions lib/routes/baoyu/namespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { Namespace } from '@/types';

export const namespace: Namespace = {
name: '宝玉',
url: 'baoyu.io',
description: '宝玉的博客',
lang: 'zh-CN',
};
22 changes: 15 additions & 7 deletions lib/routes/bilibili/dynamic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const route: Route = {
| 键 | 含义 | 接受的值 | 默认值 |
| ---------- | --------------------------------- | -------------- | ------ |
| showEmoji | 显示或隐藏表情图片 | 0/1/true/false | false |
| embed | 默认开启内嵌视频 | 任意值 | |
| embed | 默认开启内嵌视频 | 0/1/true/false | true |
| useAvid | 视频链接使用 AV 号 (默认为 BV 号) | 0/1/true/false | false |
| directLink | 使用内容直链 | 0/1/true/false | false |
| hideGoods | 隐藏带货动态 | 0/1/true/false | false |
Expand Down Expand Up @@ -117,6 +117,7 @@ const getIframe = (data?: Modules, embed: boolean = true) => {
if (aid === undefined && bvid === undefined) {
return '';
}
// 不通过 utils.renderUGCDescription 渲染 img/description 以兼容其他格式的动态
return utils.renderUGCDescription(embed, '', '', aid, undefined, bvid);
};

Expand Down Expand Up @@ -146,7 +147,10 @@ const getImgs = (data?: Modules) => {
if (major[type]?.cover) {
imgUrls.push(major[type].cover);
}
return imgUrls.map((url) => `<img src="${url}">`).join('');
return imgUrls
.filter(Boolean)
.map((url) => `<img src="${url}">`)
.join('');
};

const getUrl = (item?: Item2, useAvid = false) => {
Expand Down Expand Up @@ -226,7 +230,7 @@ async function handler(ctx) {
const uid = ctx.req.param('uid');
const routeParams = Object.fromEntries(new URLSearchParams(ctx.req.param('routeParams')));
const showEmoji = fallback(undefined, queryToBoolean(routeParams.showEmoji), false);
const embed = !ctx.req.param('embed');
const embed = fallback(undefined, queryToBoolean(routeParams.embed), true);
const displayArticle = ctx.req.query('mode') === 'fulltext';
const useAvid = fallback(undefined, queryToBoolean(routeParams.useAvid), false);
const directLink = fallback(undefined, queryToBoolean(routeParams.directLink), false);
Expand Down Expand Up @@ -255,7 +259,12 @@ async function handler(ctx) {

const rssItems = await Promise.all(
items
.filter((item) => !hideGoods || item.modules.module_dynamic?.additional?.type !== 'ADDITIONAL_TYPE_GOODS')
.filter((item) => {
if (hideGoods) {
return item.modules.module_dynamic?.additional?.type !== 'ADDITIONAL_TYPE_GOODS';
}
return true;
})
.map(async (item) => {
// const parsed = JSONbig.parse(item.card);

Expand Down Expand Up @@ -354,10 +363,9 @@ async function handler(ctx) {
// 换行处理
description = description.replaceAll('\r\n', '<br>').replaceAll('\n', '<br>');
originDescription = originDescription.replaceAll('\r\n', '<br>').replaceAll('\n', '<br>');

const descriptions = [description, originDescription, urlText, originUrlText, getIframe(data, embed), getIframe(origin, embed), getImgs(data), getImgs(origin)]
.filter(Boolean)
const descriptions = [description, getIframe(data, embed), getImgs(data), urlText, originDescription, getIframe(origin, embed), getImgs(origin), originUrlText]
.map((e) => e?.trim())
.filter(Boolean)
.join('<br>');

return {
Expand Down
4 changes: 2 additions & 2 deletions lib/routes/bilibili/followings-dynamic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const route: Route = {
| 键 | 含义 | 接受的值 | 默认值 |
| ---------- | --------------------------------- | -------------- | ------ |
| showEmoji | 显示或隐藏表情图片 | 0/1/true/false | false |
| embed | 默认开启内嵌视频 | 任意值 | |
| embed | 默认开启内嵌视频 | 0/1/true/false | true |
| useAvid | 视频链接使用 AV 号 (默认为 BV 号) | 0/1/true/false | false |
| directLink | 使用内容直链 | 0/1/true/false | false |
| hideGoods | 隐藏带货动态 | 0/1/true/false | false |
Expand Down Expand Up @@ -55,7 +55,7 @@ async function handler(ctx) {
const routeParams = querystring.parse(ctx.req.param('routeParams'));

const showEmoji = fallback(undefined, queryToBoolean(routeParams.showEmoji), false);
const embed = !ctx.req.param('embed');
const embed = fallback(undefined, queryToBoolean(routeParams.embed), true);
const displayArticle = fallback(undefined, queryToBoolean(routeParams.displayArticle), false);

const name = await cache.getUsernameFromUID(uid);
Expand Down
Loading

0 comments on commit d44cd0e

Please sign in to comment.