feat(route/mi): refactor crowdfunding with ofetch and art-template (#16974)

* feat(route/mi): refactor crowdfunding with ofetch and art-template

* fix: remove unnecessary diff

* refactor: use flatMap

---------
This commit is contained in:
nuomi1 2024-10-04 22:23:53 +08:00 committed by GitHub
parent 5747505a12
commit 5a653b6ef4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 191 additions and 22 deletions

View File

@ -1,37 +1,58 @@
import { Route } from '@/types';
import got from '@/utils/got';
import { Data, DataItem, Route, ViewType } from '@/types';
import { CrowdfundingDetailInfo, CrowdfundingList } from './types';
import utils from './utils';
export const route: Route = {
path: '/crowdfunding',
categories: ['shopping'],
example: '/mi/crowdfunding',
name: '小米众筹',
maintainers: ['DIYgod'],
maintainers: ['DIYgod', 'nuomi1'],
handler,
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportRadar: true,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
radar: [
{
source: ['m.mi.com/crowdfunding/home'],
target: '/crowdfunding',
},
],
view: ViewType.Notifications,
};
const getDetails = async (list: CrowdfundingList[]) => {
const result: Promise<CrowdfundingDetailInfo>[] = list.flatMap((section) => section.items.map((item) => utils.getCrowdfundingItem(item)));
return await Promise.all(result);
};
const getDataItem = (item: CrowdfundingDetailInfo) =>
({
title: item.project_name,
description: utils.renderCrowdfunding(item),
link: `https://m.mi.com/crowdfunding/proddetail/${item.project_id}`,
image: item.big_image,
language: 'zh-cn',
}) as DataItem;
async function handler() {
const response = await got({
method: 'post',
url: 'http://api.m.mi.com/v1/microwd/home',
headers: {
'Mishop-Client-Id': '180100031055',
'User-Agent': 'MiShop/4.3.68 (iPhone; iOS 12.0.1; Scale/3.00)',
'IOS-App-Version': '4.3.68',
'IOS-Version': 'system=12.0.1&device=iPhone10,3',
},
});
const list = response.data.data.list.flatMap((a) => a.items || []);
const list = await utils.getCrowdfundingList();
const details = await getDetails(list);
const items: DataItem[] = details.map((item) => getDataItem(item));
return {
title: '小米众筹',
link: '',
link: 'https://m.mi.com/crowdfunding/home',
item: items,
allowEmpty: true,
item:
list &&
list.map((item) => ({
title: item.product_name,
description: `<img src="${item.img_url}"><br>价格:${item.product_price}`,
})),
};
image: 'https://m.mi.com/static/img/icons/apple-touch-icon-152x152.png',
language: 'zh-cn',
} as Data;
}

View File

@ -0,0 +1,28 @@
<img src="{{ big_image }}">
<br>
{{ project_name }}
<br>
{{ project_desc }}
<br>
众筹价:{{ price }} 元,建议零售价:{{ product_market_price }} 元
<br>
众筹开始:{{ start_time_desc }},众筹结束:{{ end_time_desc }}
<br>
物流:{{ send_info }}
<br>
<table>
<tbody>
<tr>
<th>档位</th>
<th>价格</th>
<th>描述</th>
</tr>
{{ each support_list }}
<tr>
<td>{{ $value.name }}</td>
<td>{{ $value.price }} 元</td>
<td>{{ $value.support_desc }}</td>
</tr>
{{ /each }}
</tbody>
</table>

40
lib/routes/mi/types.ts Normal file
View File

@ -0,0 +1,40 @@
export interface DataResponse<Data> {
data: Data;
}
export interface CrowdfundingData {
list: CrowdfundingList[];
}
export interface CrowdfundingList {
items: CrowdfundingItem[];
}
export interface CrowdfundingItem {
project_id: number;
product_market_price: string;
}
export interface CrowdfundingDetailData {
crowd_funding_info: CrowdfundingDetailInfo;
}
export interface CrowdfundingDetailInfo {
big_image: string;
end_time: number;
end_time_desc: string; // injected
price: string;
product_market_price: string; // injected
project_desc: string;
project_id: number;
project_name: string;
start_time: number;
start_time_desc: string; // injected
support_list: CrowdfundingDetailSupportList[];
}
export interface CrowdfundingDetailSupportList {
name: string;
price: string;
support_desc: string;
}

80
lib/routes/mi/utils.ts Normal file
View File

@ -0,0 +1,80 @@
import { getCurrentPath } from '@/utils/helpers';
const __dirname = getCurrentPath(import.meta.url);
import cache from '@/utils/cache';
import ofetch from '@/utils/ofetch';
import { art } from '@/utils/render';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import timezone from 'dayjs/plugin/timezone';
import utc from 'dayjs/plugin/utc';
import path from 'path';
import { CrowdfundingData, CrowdfundingDetailData, CrowdfundingDetailInfo, CrowdfundingItem, CrowdfundingList, DataResponse } from './types';
dayjs.extend(localizedFormat);
dayjs.extend(timezone);
dayjs.extend(utc);
/**
*
*
* @returns {Promise<CrowdfundingList[]>}
*/
export const getCrowdfundingList = async (): Promise<CrowdfundingList[]> => {
const response = await ofetch<DataResponse<CrowdfundingData>>('https://m.mi.com/v1/crowd/crowd_home', {
headers: {
referrer: 'https://m.mi.com/',
},
method: 'POST',
});
return response.data.list;
};
/**
*
*
* @param {CrowdfundingItem} item -
* @returns {Promise<CrowdfundingDetailInfo>}
*/
export const getCrowdfundingItem = (item: CrowdfundingItem): Promise<CrowdfundingDetailInfo> =>
cache.tryGet(`mi:crowdfunding:${item.project_id}`, async () => {
const response = await ofetch<DataResponse<CrowdfundingDetailData>>('https://m.mi.com/v1/crowd/crowd_detail', {
headers: {
referrer: 'https://m.mi.com/crowdfunding/home',
},
method: 'POST',
query: {
project_id: item.project_id,
},
});
// 建议零售价
if (response.data.crowd_funding_info.product_market_price === undefined) {
response.data.crowd_funding_info.product_market_price = item.product_market_price;
}
// 众筹开始
if (response.data.crowd_funding_info.start_time_desc === undefined) {
response.data.crowd_funding_info.start_time_desc = formatDate(response.data.crowd_funding_info.start_time);
}
// 众筹结束
if (response.data.crowd_funding_info.end_time_desc === undefined) {
response.data.crowd_funding_info.end_time_desc = formatDate(response.data.crowd_funding_info.end_time);
}
return response.data.crowd_funding_info;
}) as Promise<CrowdfundingDetailInfo>;
/**
*
*
* @param {CrowdfundingDetailInfo} item -
* @returns {string}
*/
export const renderCrowdfunding = (item: CrowdfundingDetailInfo): string => art(path.join(__dirname, 'templates/crowdfunding.art'), item);
const formatDate = (timestamp: number): string => dayjs.unix(timestamp).tz('Asia/Shanghai').locale('zh-cn').format('lll');
export default {
getCrowdfundingList,
getCrowdfundingItem,
renderCrowdfunding,
};