import axios from "axios"; import { HttpsProxyAgent } from "https-proxy-agent"; import getDateInTimezone from "./getDateInTimezone.js"; /** * 清理对象中的undefined值 * @param {*} obj * @returns {Object} */ const cleanUndefined = (obj) => { return Object.fromEntries( Object.entries(obj).filter(([, v]) => v !== undefined) ); } const axiosDefaultOptions = { baseURL: "https://gamma-api.polymarket.com", url: "", method: "GET", headers: {}, params: {}, data: {}, timeout: 10000, }; const fetchMarketData = async (options) => { const { url } = options; if (!url) { throw new Error("url is required"); } const mergedOptions = { ...axiosDefaultOptions, ...options }; const proxy = process.env.NODE_HTTP_PROXY; if (proxy) { mergedOptions.proxy = false; mergedOptions.httpsAgent = new HttpsProxyAgent(proxy); } return axios(mergedOptions).then(res => res.data); }; /** * 获取有效联赛 * @param {*} marketsData * @param {*} soccerSports * @returns {Array} */ const getLeagues = (marketsData, soccerSports) => { const soccerSportsMap = new Map(soccerSports.map(item => [+item.series, item])); const leaguesList = marketsData.map(item => { const { leagueId: id, leagueName: name } = item; const sport = soccerSportsMap.get(+id)?.sport; return { id, name, sport }; }); const leaguesMap = new Map(leaguesList.map(item => [item.id, item])); return Array.from(leaguesMap.values()).sort((a, b) => a.id - b.id); } /** * 获取足球联赛 * @returns {Promise} */ const getSoccerSports = async () => { return fetchMarketData({ url: "/sports" }) .then(sportsData => { return sportsData.filter(item => { const { tags } = item; const tagIds = tags.split(",").map(item => +item); return tagIds.includes(100350); }); }); } /** * 解析赛事标题 * @param {*} eventTitle * @returns {Object} */ const parseTeamData = (eventTitle) => { const teamData = eventTitle.replace(' - More Markets', '').split(" vs. "); return { teamHomeName: teamData[0], teamAwayName: teamData[1], }; } /** * 解析赛事数据 * @param {*} event * @returns {Object} */ const parseEvent = (event) => { const { id, title, series, gameId, parentEventId, startTime } = event; const { teamHomeName, teamAwayName } = parseTeamData(title); const leagueId = series[0].id; const leagueName = series[0].title; const timestamp = new Date(startTime).getTime(); return { id: +id, gameId: gameId ? +gameId : undefined, parentEventId: parentEventId ? +parentEventId : undefined, leagueId: +leagueId, teamHomeName, teamAwayName, leagueName, timestamp, startTime: getDateInTimezone('+8', timestamp, true), }; } /** * 解析市场列表数据 * @param {*} events * @returns {Object} */ const parseMarkets = (events) => { return events.map(parseEvent) .filter(item => !item.parentEventId) .map(cleanUndefined) .sort((a, b) => a.timestamp - b.timestamp); } /** * 获取赛事数据 * @param {*} seriesIds * @returns {Promise} */ const getMarketsData = async (seriesIds = []) => { if (!seriesIds.length) { return []; } const endDateMin = new Date().toISOString(); const tomorrowDateMinus4 = getDateInTimezone(-4, Date.now()+24*60*60*1000); const tomorrowGmtMinus4EndTime = new Date(`${tomorrowDateMinus4} 23:59:59 GMT-4`).getTime(); const endDateMax = new Date(tomorrowGmtMinus4EndTime).toISOString(); return Promise.all(seriesIds.map(seriesId => { return fetchMarketData({ url: "/events", params: { series_id: +seriesId, active: true, closed: false, end_date_min: endDateMin, end_date_max: endDateMax, } }) })) .then(eventsDataList => eventsDataList.flat()) .then(eventsData => { return parseMarkets(eventsData); }) } /** * 获取联赛和比赛列表 * @returns {Promise} */ export const polymarketLeaguesAndGames = async () => { let soccerSports = []; return getSoccerSports() .then(sports => { soccerSports = sports; return sports.map(item => item.series) }) .then(seriesIds => getMarketsData(seriesIds)) .then(games => { const leagues = getLeagues(games, soccerSports); return { leagues, games }; }); }