Files
AutoJs6/.utils/utils/fetch.mjs
2025-09-09 17:24:48 +08:00

101 lines
3.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// utils/fetch.mjs
/** @typedef {import('@octokit/types').Endpoints['GET /repos/{owner}/{repo}/commits']['response']['data']} CommitsData */
import fetch from 'node-fetch';
import * as dotenv from 'dotenv';
import { toYYYYMMDD } from './date.mjs';
dotenv.config({ path: '../.env', quiet: true });
/**
* 获取远程文件真实大小.
*
* @param {string} url
* @param {{timeout?: number}} [options]
* @returns {Promise<number | null>}
*/
export async function getRemoteFileSizeBytes(url, { timeout = 30000 } = {}) {
const headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124 Safari/537.36',
'accept': '*/*',
};
// 1) 尝试 HEAD
try {
const res = await fetch(url, {
method: 'HEAD',
redirect: 'follow',
headers,
});
if (res.ok) {
const len = res.headers.get('content-length');
if (len && /^\d+$/.test(len)) return Number(len);
}
} catch (_) {
/* Ignored. */
}
// 2) 尝试 Range GET (bytes=0-0), 从 Content-Range 解析总长度
try {
const ac = new AbortController();
const t = setTimeout(() => ac.abort(), timeout);
const res = await fetch(url, {
method: 'GET',
redirect: 'follow',
headers: { ...headers, range: 'bytes=0-0' },
signal: ac.signal,
}).finally(() => clearTimeout(t));
if (res.ok || res.status === 206) {
// Content-Range: bytes 0-0/123456789
const cr = res.headers.get('content-range');
if (cr) {
const m = /bytes\s+\d+-\d+\/(\d+)/i.exec(cr);
if (m) return Number(m[1]);
}
// 退化: 仍然尝试 content-length
const len = res.headers.get('content-length');
if (len && /^\d+$/.test(len)) return Number(len);
}
} catch (_) {
/* Ignored. */
}
return null;
}
/**
* @param {string} owner
* @param {string} repo
* @return {Promise<string>}
*/
export async function getLatestCommitDate(owner, repo) {
const token = process.env.GITHUB_TOKEN; // 可选:避免频繁请求受限
const url = `https://api.github.com/repos/${owner}/${repo}/commits?per_page=1`;
/** @type {import('node-fetch').HeadersInit} */
const headers = {
accept: 'application/vnd.github+json',
'user-agent': 'repo-last-commit-script',
...(token ? { authorization: `Bearer ${token}` } : {}),
};
const res = await fetch(url, { headers });
if (!res.ok) {
throw new Error(`GitHub API 请求失败: ${res.status} ${res.statusText}`);
}
const data = /** @type {CommitsData} */ await res.json();
const latest = Array.isArray(data) ? data[0] : null;
if (!latest?.commit) throw new Error('未获取到最新提交');
// 优先使用 committer 的提交时间fallback 到 author
const iso = latest.commit.committer?.date ?? latest.commit.author?.date;
if (!iso) throw new Error('提交对象缺少日期字段');
return toYYYYMMDD(iso);
}