SignalMod / frontend /src /utils /toxicity.ts
Ruperth's picture
feat: add comment composer recent activity feed and random usernames
7e7e06a
raw
history blame
2.73 kB
export function toxicityColor(probability: number): string {
const pct = probability * 100;
if (pct >= 70) return "#ff4e45";
if (pct >= 40) return "#f5a623";
return "#2ba640";
}
export function formatPct(probability: number): string {
return `${Math.round(probability * 100)}%`;
}
export function newId(): string {
return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
}
const RTF = new Intl.RelativeTimeFormat("es", { numeric: "auto" });
const TIME_UNITS: Array<[Intl.RelativeTimeFormatUnit, number]> = [
["year", 60 * 60 * 24 * 365],
["month", 60 * 60 * 24 * 30],
["day", 60 * 60 * 24],
["hour", 60 * 60],
["minute", 60],
["second", 1],
];
export function relativeTime(input: string | number | Date): string {
const date = input instanceof Date ? input : new Date(input);
const seconds = (date.getTime() - Date.now()) / 1000;
if (!Number.isFinite(seconds)) return "";
for (const [unit, secondsInUnit] of TIME_UNITS) {
if (Math.abs(seconds) >= secondsInUnit || unit === "second") {
return RTF.format(Math.round(seconds / secondsInUnit), unit);
}
}
return "";
}
export function truncate(text: string, max = 140): string {
if (text.length <= max) return text;
return `${text.slice(0, max - 1).trimEnd()}…`;
}
const ADJECTIVES = [
"happy", "lucky", "wild", "calm", "bright", "swift", "quiet", "lazy",
"brave", "fuzzy", "shiny", "sleepy", "quick", "noble", "loud", "humble",
"stormy", "sunny", "rainy", "frosty", "spicy", "salty", "sweet", "crazy",
"mighty", "silent", "epic", "cosmic", "rusty", "neon", "wandering", "lone",
];
const NOUNS = [
"panda", "tiger", "falcon", "otter", "eagle", "wolf", "fox", "bear",
"lynx", "shark", "raven", "viper", "phoenix", "dragon", "jaguar", "koala",
"moose", "lion", "owl", "octopus", "rabbit", "hawk", "badger", "robin",
"cosmonaut", "drifter", "ninja", "wizard", "rider", "pilot", "skater", "gamer",
];
const SUFFIXES = ["", "_", "_", "_yt", "_hd", "_real", "99", "01", "_xd", "_v2", "_official", ""];
/**
* Generate a YouTube-style random username, deterministic per seed.
*/
export function randomUsername(seed: string | number | undefined | null): string {
const str = seed == null ? "anon" : String(seed);
let hash = 5381;
for (let i = 0; i < str.length; i++) {
hash = ((hash << 5) + hash + str.charCodeAt(i)) >>> 0;
}
const adj = ADJECTIVES[hash % ADJECTIVES.length] ?? "anon";
const noun = NOUNS[Math.floor(hash / 32) % NOUNS.length] ?? "user";
const suffix = SUFFIXES[Math.floor(hash / 1024) % SUFFIXES.length] ?? "";
const needsNum = suffix === "" || suffix.endsWith("_");
const num = needsNum ? String(hash % 1000) : "";
return `${adj}_${noun}${suffix}${num}`;
}