Skip to content

Commit

Permalink
fix(route/theinitium): Fix metadata & token expiration (#15444)
Browse files Browse the repository at this point in the history
* fix(route/theinitium): Fix metadata & token expiration

* Update full.ts

Co-authored-by: Tony <TonyRL@users.noreply.github.com>

* fix: split theinitium

---------
  • Loading branch information
peng1999 authored May 2, 2024
1 parent c2510e0 commit cf4f2d2
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 14 deletions.
23 changes: 23 additions & 0 deletions lib/routes/theinitium/author.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Route } from '@/types';
import { processFeed } from './utils';

const handler = (ctx) => processFeed('author', ctx);

export const route: Route = {
path: '/author/:type/:language?',
name: '作者',
maintainers: ['AgFlore'],
parameters: {
type: '作者 ID,可从作者主页 URL 中获取,如 `https://theinitium.com/author/ninghuilulu`',
language: '语言,简体`zh-hans`,繁体`zh-hant`,缺省为简体',
},
radar: [
{
source: ['theinitium.com/author/:type'],
target: '/author/:type',
},
],
handler,
example: '/theinitium/author/ninghuilulu/zh-hans',
categories: ['new-media'],
};
28 changes: 28 additions & 0 deletions lib/routes/theinitium/channel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Route } from '@/types';
import { processFeed } from './utils';

const handler = (ctx) => processFeed('channel', ctx);

export const route: Route = {
path: '/channel/:type?/:language?',
name: '专题・栏目',
maintainers: ['prnake'],
parameters: {
type: '栏目,缺省为最新',
language: '语言,简体`zh-hans`,繁体`zh-hant`,缺省为简体',
},
radar: [
{
source: ['theinitium.com/channel/:type'],
target: '/channel/:type',
},
],
handler,
example: '/theinitium/channel/latest/zh-hans',
categories: ['new-media'],
description: `Type 栏目:
| 最新 | 深度 | What’s New | 广场 | 科技 | 风物 | 特约 | ... |
| ------ | ------- | ---------- | ----------------- | ---------- | ------- | -------- | --- |
| latest | feature | news-brief | notes-and-letters | technology | culture | pick_up | ... |`,
};
48 changes: 48 additions & 0 deletions lib/routes/theinitium/follow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Route } from '@/types';
import { processFeed } from './utils';

const handler = (ctx) => processFeed('follow', ctx);

export const route: Route = {
path: '/follow/articles/:language?',
name: '个人订阅追踪动态',
maintainers: ['AgFlore'],
parameters: {
language: '语言,简体`zh-hans`,繁体`zh-hant`,缺省为简体',
},
radar: [
{
title: '作者',
source: ['theinitium.com/author/:type'],
target: '/author/:type',
},
],
handler,
example: '/theinitium/author/ninghuilulu/zh-hans',
categories: ['new-media'],
description: 'Web 版认证 token 和 iOS 内购回执认证 token 只需选择其一填入即可。你也可选择直接在环境设置中填写明文的用户名和密码',
features: {
requireConfig: [
{
name: 'INITIUM_BEARER_TOKEN',
optional: true,
description: `端传媒 Web 版认证 token。获取方式:登陆后打开端传媒站内任意页面,打开浏览器开发者工具中 “网络”(Network) 选项卡,筛选 URL 找到任一个地址为 \`api.initium.com\` 开头的请求,点击检查其 “消息头”,在 “请求头” 中找到Authorization字段,将其值复制填入配置即可。你的配置应该形如 \`INITIUM_BEARER_TOKEN: 'Bearer eyJxxxx......xx_U8'\`。使用 token 部署的好处是避免占据登陆设备数的额度,但这个 token 一般有效期为两周,因此只可作临时测试使用。`,
},
{
name: 'INITIUM_IAP_RECEIPT',
optional: true,
description: `端传媒 iOS 版内购回执认证 token。获取方式:登陆后打开端传媒 iOS app 内任意页面,打开抓包工具,筛选 URL 找到任一个地址为 \`api.initium.com\` 开头的请求,点击检查其 “消息头”,在 “请求头” 中找到 \`X-IAP-Receipt\` 字段,将其值复制填入配置即可。你的配置应该形如 \`INITIUM_IAP_RECEIPT: ef81dee9e4e2fe084a0af1ea82da2f7b16e75f756db321618a119fa62b52550e\`。`,
},
{
name: 'INITIUM_USERNAME',
optional: true,
description: `端传媒用户名 (邮箱)`,
},
{
name: 'INITIUM_PASSWORD',
optional: true,
description: `端传媒密码`,
},
],
},
};
23 changes: 23 additions & 0 deletions lib/routes/theinitium/tags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Route } from '@/types';
import { processFeed } from './utils';

const handler = (ctx) => processFeed('tags', ctx);

export const route: Route = {
path: '/tags/:type/:language?',
name: '话题・标签',
maintainers: ['AgFlore'],
parameters: {
type: '话题 ID,可从话题页 URL 中获取,如 `https://theinitium.com/tags/2019_10/`',
language: '语言,简体`zh-hans`,繁体`zh-hant`,缺省为简体',
},
radar: [
{
source: ['theinitium.com/tags/:type'],
target: '/tags/:type',
},
],
handler,
example: '/theinitium/tags/2019_10/zh-hans',
categories: ['new-media'],
};
33 changes: 19 additions & 14 deletions lib/routes/theinitium/full.ts → lib/routes/theinitium/utils.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
import { Route } from '@/types';
import { Context } from 'hono';
import cache from '@/utils/cache';
import got from '@/utils/got';
import { config } from '@/config';
import { load } from 'cheerio';
import { parseDate } from '@/utils/parse-date';
import InvalidParameterError from '@/errors/types/invalid-parameter';
import { FetchError } from 'ofetch';

const TOKEN = 'Basic YW5vbnltb3VzOkdpQ2VMRWp4bnFCY1ZwbnA2Y0xzVXZKaWV2dlJRY0FYTHY=';

export const route: Route = {
path: '/:model?/:type?/:language?',
name: 'Unknown',
maintainers: [],
handler,
};

async function handler(ctx) {
export const processFeed = async (model: string, ctx: Context) => {
// model是channel/tag/etc.,而type是latest/feature/quest-academy这些一级栏目/标签/作者名的slug名。如果是追踪的话,那就是model是follow,type是articles。
const model = ctx.req.param('model') ?? 'channel';
const type = ctx.req.param('type') ?? 'latest';
const language = ctx.req.param('language') ?? 'zh-hans';
let listUrl;
Expand All @@ -38,6 +32,8 @@ async function handler(ctx) {
listUrl = `https://api.theinitium.com/api/v2/tag/articles/?language=${language}&slug=${type}`;
listLink = `https://theinitium.com/tags/${type}/`;
break;
default:
throw new InvalidParameterError('wrong model');
}

const key = {
Expand Down Expand Up @@ -92,9 +88,18 @@ async function handler(ctx) {
'X-IAP-Receipt': key.iapReceipt || '',
};

const response = await got(listUrl, {
headers,
});
let response;
try {
response = await got(listUrl, {
headers,
});
} catch (error) {
if (error instanceof FetchError && error.statusCode === 401) {
// 401 说明 token 过期了,将它删掉
await cache.set('initium:token', '');
}
throw error;
}

const name = response.data.name || (response.data[model] && response.data[model].name) || '追踪';
// 从v1直升的channel和tags里面是digests,v2新增的author和follow出来都是results
Expand Down Expand Up @@ -175,4 +180,4 @@ async function handler(ctx) {
item: items,
image,
};
}
};

0 comments on commit cf4f2d2

Please sign in to comment.