| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- const sinceInput = document.querySelector('#since') as HTMLInputElement;
- const newbies = document.querySelector('textarea#newbies') as HTMLTextAreaElement;
- {
- const twoDaysAgo = new Date();
- twoDaysAgo.setUTCDate(twoDaysAgo.getUTCDate() - 2);
- twoDaysAgo.setUTCHours(0, 0, 0, 0);
- sinceInput.value = twoDaysAgo.toISOString().slice(0, 10);
- }
- let planets: string[];
- export function setupNewbies(setPlanets: string[]): void {
- planets = setPlanets;
- render();
- }
- sinceInput.addEventListener('change', () => void render());
- async function render(): Promise<void> {
- const loader = document.querySelector('#loader') as HTMLElement;
- loader.style.display = 'block';
- try {
- await _render();
- } catch (e) {
- console.error(e);
- }
- loader.style.display = 'none';
- }
- async function _render(): Promise<void> {
- if (sinceInput.valueAsDate === null) {
- console.warn(sinceInput.value, 'is not a valid date');
- newbies.value = '';
- return;
- }
- newbies.style.display = 'none';
- const joined: Map<string, Join> = new Map();
- for (const planet of planets) {
- const messages: Message[] = await fetchJSON('https://api.fnar.net/chat/messages?' +
- new URLSearchParams({'channel_names': planet + ' Global Site Owners'}).toString());
- for (const message of messages)
- if (message.Type == 'JOINED') {
- const oldJoin = joined.get(message.SenderUserName)
- if (oldJoin === undefined || oldJoin.timestamp > message.MessageTimestamp)
- joined.set(message.SenderUserName, {timestamp: message.MessageTimestamp, planet});
- }
- }
- const threshold = sinceInput.valueAsDate!.getTime();
- const sortedJoined = Array.from(joined.entries().filter(([_, join]) => join.timestamp >= threshold))
- .sort((a, b) => a[1].timestamp - b[1].timestamp);
- const reputation = await getReputations(sortedJoined.map(([username, _]) => username));
- const lines: string[] = [];
- for (const [username, join] of sortedJoined) {
- const dtStr = new Date(join.timestamp).toISOString().replace('T', ' ').replace('Z', '');
- lines.push(`${username}\t${dtStr}\t${join.planet}\t${reputation.get(username) ?? ''}`);
- }
- newbies.value = lines.join('\n');
- newbies.style.display = 'block';
- }
- async function getReputations(usernames: string[]): Promise<Map<string, number>> {
- const relevantCos = new Set<string>();
- for (const username of usernames) {
- const response = await fetch('https://rest.fnar.net/user/' + encodeURIComponent(username));
- if (response.status !== 204) {
- const companyCode = (await response.json()).CompanyCode;
- relevantCos.add(companyCode);
- }
- }
- const reputation = new Map<string, number>();
- const companyCodes = Array.from(relevantCos);
- for (let start = 0; start < companyCodes.length; start += 10) {
- const batch = companyCodes.slice(start, start + 10);
- const companies: Company[] = await fetchJSON('https://api.fnar.net/company/lookup?' +
- batch.map((companyCode) => 'company=' + encodeURIComponent(companyCode)).join('&'));
- for (const company of companies)
- if (company !== null && company.UserName !== null)
- reputation.set(company.UserName.toLowerCase(), company.Reputation);
- }
- return reputation;
- }
- document.querySelector('#copy')!.addEventListener('click', () => {
- navigator.clipboard.writeText(newbies.value);
- });
- async function fetchJSON(url: string, options: RequestInit = {}): Promise<any> {
- const controller = new AbortController();
- const timeoutId = setTimeout(() => controller.abort(), 5000);
- const doc = await fetch(url, {...options, signal: controller.signal}).then((r) => r.json());
- clearTimeout(timeoutId);
- return doc;
- }
- interface Message {
- Type: string;
- MessageTimestamp: number;
- SenderUserName: string;
- }
- interface Join {
- timestamp: number;
- planet: string;
- }
- interface Company {
- UserName: string | null;
- CompanyCode: string;
- Reputation: number;
- }
|