Skip to content

Commit

Permalink
feat(route/mi): refactor crowdfunding with ofetch and art-template (D…
Browse files Browse the repository at this point in the history
…IYgod#16974)

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

* fix: remove unnecessary diff

* refactor: use flatMap

---------
  • Loading branch information
nuomi1 authored Oct 4, 2024
1 parent 5747505 commit 5a653b6
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 22 deletions.
65 changes: 43 additions & 22 deletions lib/routes/mi/crowdfunding.ts
Original file line number Diff line number Diff line change
@@ -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;
}
28 changes: 28 additions & 0 deletions lib/routes/mi/templates/crowdfunding.art
Original file line number Diff line number Diff line change
@@ -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 changes: 40 additions & 0 deletions lib/routes/mi/types.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 80 additions & 0 deletions lib/routes/mi/utils.ts
Original file line number Diff line number Diff line change
@@ -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,
};

0 comments on commit 5a653b6

Please sign in to comment.