Skip to content

Instantly share code, notes, and snippets.

@Celeo
Last active July 11, 2022 03:19
Show Gist options
  • Save Celeo/09b8ea760d2763f51fdcfed2e0f0c65b to your computer and use it in GitHub Desktop.
Save Celeo/09b8ea760d2763f51fdcfed2e0f0c65b to your computer and use it in GitHub Desktop.
import { parse, HTMLElement } from "https://esm.sh/node-html-parser@5.3.3";
/**
* A single connection's information.
*/
export interface ConnectionItem {
id: number;
vatsim_id: string;
type: number;
rating: number;
callsign: string;
start: string;
end: string | null;
server: string;
}
/**
* A single ATC session's information.
*/
export interface AtcSession {
start: string;
end: string;
callsign: string;
minutes_on_callsign: number;
}
/**
* ZLA member information.
*/
export interface Member {
name: string;
cid: number;
}
/**
* Get all of a user's connections by CID.
*
* This function returns all connections, including those
* of the user as a pilot and observer.
*/
export async function getConnections(
cid: number
): Promise<Array<ConnectionItem>> {
const resp = await fetch(
`https://api.vatsim.net/api/ratings/${cid}/connections/`
);
if (resp.status !== 200) {
throw new Error(`Got status ${resp.status} from connections endpoint`);
}
const data: { results: Array<Record<string, unknown>> } = await resp.json();
return data.results.map((entry) => {
return {
id: entry.id as number,
vatsim_id: entry.vatsim_id as string,
type: entry.type as number,
rating: entry.rating as number,
callsign: entry.callsign as string,
start: entry.start as string,
end: entry?.end as string,
server: entry.server as string,
};
});
}
/**
* Get all of a user's ATC sessions by CID.
*
* This function only returns active controller sessions, i.e.
* no piloting and no observing.
*/
export async function getSessions(cid: number): Promise<Array<AtcSession>> {
const resp = await fetch(
`https://api.vatsim.net/api/ratings/${cid}/actsessions/`
);
if (resp.status !== 200) {
throw new Error(`Got status ${resp.status} from atcsessions endpoint`);
}
const data: { results: Array<Record<string, unknown>> } = await resp.json();
return data.results.map((entry) => {
return {
start: entry.start as string,
end: entry?.end as string,
callsign: entry.callsign as string,
minutes_on_callsign: parseFloat(entry.minutes_on_callsign as string),
};
});
}
/**
* Get all ZLA members by scraping their roster page.
*/
export async function getZlaMembers(): Promise<Array<Member>> {
const resp = await fetch("https://laartcc.org/roster");
if (resp.status !== 200) {
throw new Error(`Got status ${resp.status} from ZLA members endpoint`);
}
const root = parse(await resp.text());
const rows = root.querySelector("#roster")?.querySelectorAll("tr") ?? [];
return rows
.map((row) => row.querySelector("a"))
.filter((link): link is HTMLElement => link !== null)
.map((link) => {
const name = link.innerHTML;
const cid = parseInt(link.getAttribute("href")!.split("/")[4]);
return { name, cid };
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment