import type { IEventInfo, Player } from "../types"; import * as cheerio from "cheerio"; import { chunk } from 'lodash'; export const BASE_URL = `https://kaiqiuwang.cc`; const htmlRequestHeaders = { "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8", "accept-language": "zh-CN,zh;q=0.8", "cache-control": "max-age=0", "priority": "u=0, i", "sec-ch-ua": "\"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"144\", \"Brave\";v=\"144\"", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "\"Windows\"", "sec-fetch-dest": "document", "sec-fetch-mode": "navigate", "sec-fetch-site": "none", "sec-fetch-user": "?1", "sec-gpc": "1", "upgrade-insecure-requests": "1", "cookie": "SECKEY_ABVK=oTGgqH4ypGPFVdQ3J9K7PoAOPdZ+8R7CsUzi75gelcg%3D; uchome_sendmail=1" } /** * @param tagid 俱乐部 ID */ export async function listEvent(tagid: string): Promise { return parseEventList(await fetchEventListHTML(tagid)); } /** * @param tagid 俱乐部 ID * @return HTML */ export async function fetchEventListHTML(tagid: string) { const url = `${BASE_URL}/home/space.php?do=mtag&tagid=${tagid}&view=event`; const resp = await fetch(url, { headers: htmlRequestHeaders }); return resp.text() ?? ''; } export function parseEventList(html: string) { const $ = cheerio.load(html); const blockList = $('div.event_list > ol > li'); const list: IEventInfo[] = []; for (const block of blockList) { const titleEl = $(block).find('.event_title'); const title = titleEl.text(); const url = $(titleEl).find('a').attr('href') ?? ''; const startDate = $(block).find('ul li:nth-of-type(1)').text().replace('比赛开始: \\t', '').trim(); const place = $(block).find('ul li:nth-of-type(2)').text().replace('比赛地点: \\t', '').trim(); const event: IEventInfo = { title, info: [startDate, place], url: `${BASE_URL}/home/${url}`, matchId: /\S+-(\d+).html$/.exec(url)?.[1] ?? '', } list.push(event); } return list; } /** * * @param matchId 比赛 ID * @returns HTML */ export async function fetchEventContentHTML(matchId: string) { const url = `${BASE_URL}/home/space.php?do=event&id=${matchId}&view=member&status=2`; const resp = await fetch(url, { headers: htmlRequestHeaders }); return resp.text() ?? '' } export function parseEventInfo(html: string) { const $ = cheerio.load(html); const title = $('h2.title a').text(); const itemHref = $('.sub_menu a.active').attr('href') ?? ''; const itemId = /\S+item_id=(\d+)$/.exec(itemHref)?.[1] ?? ''; const players: Player[] = []; const playersEl = $('.thumb'); for (const player of playersEl) { const img = $(player).find('.image img').attr('src') ?? ''; const name = $(player).find('h6').text().trim(); const uid = /space-(?\d+).html/.exec($(player).find('h6 a').attr('href') ?? '')?.groups?.uid ?? ''; const info = $(player).find('p:nth-of-type(2)').text().replace(/\s/g, ''); const score = /^.*?\b(\d+)\b/.exec(info)?.[1] ?? ''; players.push({ name, avatar: img, score, info, uid }); } return { itemId, title, players, } } export async function getMatchInfo(matchId: string) { return parseEventInfo(await fetchEventContentHTML(matchId)); } export function sneckGroup(size: number, groupLen: number) { const indexArray = new Array(size).fill(0).map((_, i) => i); const chunckSize = Math.round((size / groupLen)); const chunckedGroup = chunk(indexArray, groupLen); const reversedGroup = chunckedGroup.map((e, i) => { if (i % 2 === 0) return e; return e.toReversed(); }); const newGroups: number[][] = []; for (let groupIndex = 0; groupIndex < groupLen; groupIndex++) { const group: number[] = []; for (let colIndex = 0; colIndex < chunckSize; colIndex++) { const data = reversedGroup[colIndex]?.[groupIndex]; group.push(data === undefined ? NaN : data); } newGroups.push(group); } return newGroups; } export function getRoundTable(nameList: T[], round: number) { const list = [...nameList]; const half = list.length / 2; if (round > list.length - 1) { const left = [...list].slice(0, half); const right = [...list].slice(half); return [left, right]; } const sliceStart = (list.length) - round; const slice = list.slice(sliceStart); // console.debug(JSON.stringify({ list })); list.splice(sliceStart); const [first, ...others] = list; const newList = [first, ...slice, ...others].filter(Boolean); // console.debug(JSON.stringify({ sliceStart, len: list.length, first, others, slice, newList })); const left = [...newList].slice(0, half); const right = [...newList].slice(half).reverse(); return [left, right]; } export function createGameID(matchId: string, user1: string, user2: string) { return [matchId, user1, user2].join('-'); }