scripts: exclude unresolved clawtributors from README

This commit is contained in:
Shakker 2026-02-24 02:53:30 +00:00
parent 90383e00e9
commit ef1ffacfb2
No known key found for this signature in database

View File

@ -15,7 +15,6 @@ const emailToLogin = normalizeMap(mapConfig.emailToLogin ?? {});
const ensureLogins = (mapConfig.ensureLogins ?? []).map((login) => login.toLowerCase()); const ensureLogins = (mapConfig.ensureLogins ?? []).map((login) => login.toLowerCase());
const readmePath = resolve("README.md"); const readmePath = resolve("README.md");
const placeholderAvatar = mapConfig.placeholderAvatar ?? "assets/avatar-placeholder.svg";
const seedCommit = mapConfig.seedCommit ?? null; const seedCommit = mapConfig.seedCommit ?? null;
const seedEntries = seedCommit ? parseReadmeEntries(run(`git show ${seedCommit}:README.md`)) : []; const seedEntries = seedCommit ? parseReadmeEntries(run(`git show ${seedCommit}:README.md`)) : [];
const raw = run(`gh api "repos/${REPO}/contributors?per_page=100&anon=1" --paginate`); const raw = run(`gh api "repos/${REPO}/contributors?per_page=100&anon=1" --paginate`);
@ -98,33 +97,33 @@ for (const login of ensureLogins) {
const entriesByKey = new Map<string, Entry>(); const entriesByKey = new Map<string, Entry>();
for (const seed of seedEntries) { for (const seed of seedEntries) {
const login = loginFromUrl(seed.html_url); const login =
const resolvedLogin = loginFromUrl(seed.html_url) ??
login ?? resolveLogin(seed.display, null, apiByLogin, nameToLogin, emailToLogin); resolveLogin(seed.display, null, apiByLogin, nameToLogin, emailToLogin);
const key = resolvedLogin ? resolvedLogin.toLowerCase() : `name:${normalizeName(seed.display)}`; if (!login) {
const avatar = continue;
seed.avatar_url && !isGhostAvatar(seed.avatar_url) }
? normalizeAvatar(seed.avatar_url) const key = login.toLowerCase();
: placeholderAvatar; const user = apiByLogin.get(key) ?? fetchUser(login);
if (!user) {
continue;
}
apiByLogin.set(key, user);
const existing = entriesByKey.get(key); const existing = entriesByKey.get(key);
if (!existing) { if (!existing) {
const user = resolvedLogin ? apiByLogin.get(key) : null;
entriesByKey.set(key, { entriesByKey.set(key, {
key, key,
login: resolvedLogin ?? login ?? undefined, login: user.login,
display: seed.display, display: seed.display,
html_url: user?.html_url ?? seed.html_url, html_url: user.html_url,
avatar_url: user?.avatar_url ?? avatar, avatar_url: user.avatar_url,
lines: 0, lines: 0,
}); });
} else { } else {
existing.display = existing.display || seed.display; existing.display = existing.display || seed.display;
if (existing.avatar_url === placeholderAvatar || !existing.avatar_url) { existing.login = user.login;
existing.avatar_url = avatar; existing.html_url = user.html_url;
} existing.avatar_url = user.avatar_url;
if (!existing.html_url || existing.html_url.includes("/search?q=")) {
existing.html_url = seed.html_url;
}
} }
} }
@ -138,52 +137,37 @@ for (const item of contributors) {
? item.login ? item.login
: resolveLogin(baseName, item.email ?? null, apiByLogin, nameToLogin, emailToLogin); : resolveLogin(baseName, item.email ?? null, apiByLogin, nameToLogin, emailToLogin);
if (resolvedLogin) { if (!resolvedLogin) {
const key = resolvedLogin.toLowerCase();
const existing = entriesByKey.get(key);
if (!existing) {
let user = apiByLogin.get(key) ?? fetchUser(resolvedLogin);
if (user) {
const lines = linesByLogin.get(key) ?? 0;
const contributions = contributionsByLogin.get(key) ?? 0;
entriesByKey.set(key, {
key,
login: user.login,
display: pickDisplay(baseName, user.login, existing?.display),
html_url: user.html_url,
avatar_url: normalizeAvatar(user.avatar_url),
lines: lines > 0 ? lines : contributions,
});
}
} else if (existing) {
existing.login = existing.login ?? resolvedLogin;
existing.display = pickDisplay(baseName, existing.login, existing.display);
if (existing.avatar_url === placeholderAvatar || !existing.avatar_url) {
const user = apiByLogin.get(key) ?? fetchUser(resolvedLogin);
if (user) {
existing.html_url = user.html_url;
existing.avatar_url = normalizeAvatar(user.avatar_url);
}
}
const lines = linesByLogin.get(key) ?? 0;
const contributions = contributionsByLogin.get(key) ?? 0;
existing.lines = Math.max(existing.lines, lines > 0 ? lines : contributions);
}
continue; continue;
} }
const anonKey = `name:${normalizeName(baseName)}`; const key = resolvedLogin.toLowerCase();
const existingAnon = entriesByKey.get(anonKey); const user = apiByLogin.get(key) ?? fetchUser(resolvedLogin);
if (!existingAnon) { if (!user) {
entriesByKey.set(anonKey, { continue;
key: anonKey, }
display: baseName, apiByLogin.set(key, user);
html_url: fallbackHref(baseName),
avatar_url: placeholderAvatar, const existing = entriesByKey.get(key);
lines: item.contributions ?? 0, if (!existing) {
const lines = linesByLogin.get(key) ?? 0;
const contributions = contributionsByLogin.get(key) ?? 0;
entriesByKey.set(key, {
key,
login: user.login,
display: pickDisplay(baseName, user.login),
html_url: user.html_url,
avatar_url: normalizeAvatar(user.avatar_url),
lines: lines > 0 ? lines : contributions,
}); });
} else { } else {
existingAnon.lines = Math.max(existingAnon.lines, item.contributions ?? 0); existing.login = user.login;
existing.display = pickDisplay(baseName, user.login, existing.display);
existing.html_url = user.html_url;
existing.avatar_url = normalizeAvatar(user.avatar_url);
const lines = linesByLogin.get(key) ?? 0;
const contributions = contributionsByLogin.get(key) ?? 0;
existing.lines = Math.max(existing.lines, lines > 0 ? lines : contributions);
} }
} }
@ -205,14 +189,6 @@ for (const [login, lines] of linesByLogin.entries()) {
avatar_url: normalizeAvatar(user.avatar_url), avatar_url: normalizeAvatar(user.avatar_url),
lines: lines > 0 ? lines : contributions, lines: lines > 0 ? lines : contributions,
}); });
} else {
entriesByKey.set(login, {
key: login,
display: login,
html_url: fallbackHref(login),
avatar_url: placeholderAvatar,
lines,
});
} }
} }
@ -323,10 +299,6 @@ function normalizeAvatar(url: string): string {
return `${url}${sep}s=48`; return `${url}${sep}s=48`;
} }
function isGhostAvatar(url: string): boolean {
return url.toLowerCase().includes("ghost.png");
}
function fetchUser(login: string): User | null { function fetchUser(login: string): User | null {
const normalized = normalizeLogin(login); const normalized = normalizeLogin(login);
if (!normalized) { if (!normalized) {