lefengyang
2026-08-20 d01a28cb030b2cb0ff1d42273c877a0f728519a6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import {IPage, ISearchItem, ISearchParams, ISearchProvider, Order, Shipping, Sort, StationId} from "../type";
import {Mercapi, SearchOptions, SortBy, SortOrder} from "mercapi";
import {beginToPage} from "../lib";
 
/**
 * 煤炉(Mercari)搜索服务提供者
 */
export class Provider2Mercari implements ISearchProvider {
    readonly stationId = StationId.Mercari;
 
    async search(params: ISearchParams): Promise<IPage> {
        const maxNum = 120;
        const {keyword, minPrice, maxPrice, shipping, sort, order, category, begin = 1, maxNum: mn} = params;
 
        const pageNum = beginToPage(begin, maxNum);
 
        const ops: SearchOptions = {
            priceMin: minPrice,
            priceMax: maxPrice,
            pageToken: `v1:${pageNum - 1}`
        };
        if (shipping === Shipping.Free) {
            ops.shippingPayer = [1]
        }
        const warn: string[] = [];
        if (category) {
            const cId = parseInt(category)
            if (isNaN(cId)) {
                warn.push(`Category ${category} is not a number`);
            } else {
                ops.categories = [cId];
            }
        }
        if (sort) {
            if (sort === Sort.Latest) {
                ops.sortBy = SortBy.CreatedTime
                if (order === Order.Asc) {
                    ops.sortOrder = SortOrder.Asc;
                } else {
                    ops.sortOrder = SortOrder.Desc;
                }
            } else if (sort === Sort.Price) {
                ops.sortBy = SortBy.Price;
                if (order === Order.Desc) {
                    ops.sortOrder = SortOrder.Desc;
                } else {
                    ops.sortOrder = SortOrder.Asc;
                }
            } else if (sort !== Sort.Default) {
                warn.push(`unsupported sort=${sort}`);
            }
        }
 
        if (mn) {
            warn.push(`unsupported maxNum=${mn}`);
        }
 
        try {
            const results = await Mercapi.search(keyword, ops);
            const dataList: ISearchItem[] = results.items.map(item => ({
                itemId: item.id,
                name: item.name,
                price: item.price,
                url: ['https://jp.mercari.com', item.isShopItem ? 'shops/product' : 'item', item.id].join('/'),
                image: {
                    imageUrl: item.thumbnails?.[0],
                },
            }));
 
            return {
                warning: warn.join(', '),
                total: results.meta.numFound || dataList.length,
                ...params,
                begin,
                maxNum,
                pageNum,
                dataList,
            };
        } catch (error: any) {
            return {
                warning: warn.join(', '),
                ...params,
                begin,
                maxNum,
                pageNum,
                dataList: [],
                error: error.message || "An unknown error occurred with Mercari search",
            };
        }
    }
}