Add documentation and comments

This commit is contained in:
Clarence Chan committed 2023-10-04 14:30:57 -04:00
1 parent 065ea870da
commit 0b89eadd55
2 files changed
+63

No files matched your search

+16
View File
@@ -2,11 +2,19 @@ import { getAllDetailedEvents } from "./scrape.js";
import { writeFileSync } from "fs"; import { writeFileSync } from "fs";
import { createEvents } from "ics"; import { createEvents } from "ics";
/**
* Extracts the details of recent and near-future UFC events, then creates an
* ICS file named "UFC.ics" in the current directory containing these events
*
* @returns {Promise<void>} - A Promise that resolves when the ICS file is created
*/
async function createICS() { async function createICS() {
try { try {
let events = await getAllDetailedEvents(); let events = await getAllDetailedEvents();
if (!events.length) throw new Error("No events retrieved"); if (!events.length) throw new Error("No events retrieved");
// Get current date and time to communicate to the user how up-to-date
// the event details are
let currentDateTime = new Date(); let currentDateTime = new Date();
let dateTimestr = currentDateTime.toLocaleString("en-US", { let dateTimestr = currentDateTime.toLocaleString("en-US", {
month: "short", month: "short",
@@ -17,6 +25,7 @@ async function createICS() {
timeZoneName: "short", timeZoneName: "short",
}); });
// Convert event details in the format in accordance with the ICS generator
events = events.map((event) => { events = events.map((event) => {
let date = new Date(parseInt(event.date) * 1000); let date = new Date(parseInt(event.date) * 1000);
let start = [ let start = [
@@ -29,6 +38,9 @@ async function createICS() {
let duration = { hours: 3 }; let duration = { hours: 3 };
let title = event.name; let title = event.name;
let description = ""; let description = "";
// Distinguish between main card and prelims if this information has been
// announced by the UFC, otherwise list all fights without categorizing
if (event.fightCard.length) if (event.fightCard.length)
description += event.fightCard.join("\n") + "\n"; description += event.fightCard.join("\n") + "\n";
if (event.mainCard.length) if (event.mainCard.length)
@@ -37,8 +49,10 @@ async function createICS() {
if (event.prelims.length) if (event.prelims.length)
description += description +=
"\nPrelims\n----------\n" + event.prelims.join("\n") + "\n"; "\nPrelims\n----------\n" + event.prelims.join("\n") + "\n";
description += "\n" + event.url; description += "\n" + event.url;
description += "\n\nAccurate as of " + dateTimestr; description += "\n\nAccurate as of " + dateTimestr;
let location = event.location; let location = event.location;
let uid = event.url; let uid = event.url;
let calName = "UFC"; let calName = "UFC";
@@ -55,6 +69,8 @@ async function createICS() {
console.log("\nDetailed events:"); console.log("\nDetailed events:");
console.log(events); console.log(events);
// Create UFC.ics
writeFileSync(`UFC.ics`, createEvents(events).value); writeFileSync(`UFC.ics`, createEvents(events).value);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
+47
View File
@@ -1,16 +1,25 @@
import { parse } from "node-html-parser"; import { parse } from "node-html-parser";
import { decode } from "html-entities"; import { decode } from "html-entities";
/**
* Returns an array of URL strings of recent and near-future UFC events
*
* @returns {Promise<Array<string>>} - A Promise that resolves with the array
* of URL strings of UFC events
*/
async function getEventLinks() { async function getEventLinks() {
let url = `https://www.ufc.com/events`; let url = `https://www.ufc.com/events`;
try { try {
const response = await fetch(url); const response = await fetch(url);
const text = await response.text(); const text = await response.text();
const root = parse(text); const root = parse(text);
// Extract the URLs of the relevant events from the DOM object
let links = root.querySelectorAll(".c-card-event--result__headline"); let links = root.querySelectorAll(".c-card-event--result__headline");
links = links.map( links = links.map(
(html) => "https://www.ufc.com" + html.firstChild.getAttribute("href") (html) => "https://www.ufc.com" + html.firstChild.getAttribute("href")
); );
console.log("\nEvent links found:"); console.log("\nEvent links found:");
console.log(links); console.log(links);
return links; return links;
@@ -19,11 +28,20 @@ async function getEventLinks() {
} }
} }
/**
* Returns the fight card details of a UFC event given its URL
*
* @param {string} url - A URL string of a UFC event
* @returns {Promise<object>} - A Promise that resolves with the fight card details of
* the UFC event
*/
async function getDetailsFromEventLink(url) { async function getDetailsFromEventLink(url) {
try { try {
const response = await fetch(url); const response = await fetch(url);
const text = await response.text(); const text = await response.text();
const root = parse(text); const root = parse(text);
// Extract basic details of the event from the DOM object
let name = root.querySelector("title").innerText.replace(" | UFC", ""); let name = root.querySelector("title").innerText.replace(" | UFC", "");
let date = root let date = root
.querySelector(".c-hero__headline-suffix") .querySelector(".c-hero__headline-suffix")
@@ -36,8 +54,17 @@ async function getDetailsFromEventLink(url) {
let mainCard = root.querySelectorAll("#main-card .l-listing__item"); let mainCard = root.querySelectorAll("#main-card .l-listing__item");
let prelims = []; let prelims = [];
/**
* Helper function to return the string of a fight given its DOM list item
*
* @param {object} li - The DOM list item of a fight
* @returns {string} - The string of a fight
*/
function convertLiToStr(li) { function convertLiToStr(li) {
let bout = li.querySelector(".c-listing-fight__class-text")?.innerText; let bout = li.querySelector(".c-listing-fight__class-text")?.innerText;
// Return only fight names without bout weightclass if formatting for
// an event is broken on the UFC event page
if (!bout) if (!bout)
return ( return (
"• " + "• " +
@@ -46,6 +73,8 @@ async function getDetailsFromEventLink(url) {
.innerText.trim() .innerText.trim()
.replace(" vs ", " vs. ") .replace(" vs ", " vs. ")
); );
// Convert weightclass to lbs
if (bout.includes("Strawweight")) bout = "115"; if (bout.includes("Strawweight")) bout = "115";
else if (bout.includes("Flyweight")) bout = "125"; else if (bout.includes("Flyweight")) bout = "125";
else if (bout.includes("Bantamweight")) bout = "135"; else if (bout.includes("Bantamweight")) bout = "135";
@@ -57,6 +86,7 @@ async function getDetailsFromEventLink(url) {
else if (bout.includes("Heavyweight")) bout = "265"; else if (bout.includes("Heavyweight")) bout = "265";
else if (bout.includes("Catchweight")) bout = "CW"; else if (bout.includes("Catchweight")) bout = "CW";
// Extract and format fighter names with weightclass
let red = li let red = li
.querySelector(".c-listing-fight__corner-name--red") .querySelector(".c-listing-fight__corner-name--red")
.innerText.replaceAll("\n", "") .innerText.replaceAll("\n", "")
@@ -80,13 +110,18 @@ async function getDetailsFromEventLink(url) {
(ranks[1] ? " (" + ranks[1] + ")" : "") + (ranks[1] ? " (" + ranks[1] + ")" : "") +
" @" + " @" +
bout; bout;
// Deentitize HTML entities
fightStr = decode(fightStr); fightStr = decode(fightStr);
return fightStr; return fightStr;
} }
console.log("\nGetting details from url:", url); console.log("\nGetting details from url:", url);
// Check if main card & prelims have been announced
if (mainCard.length) { if (mainCard.length) {
// Main card has been announced, extract prelims
prelims = root.querySelectorAll("#prelims-card .l-listing__item"); prelims = root.querySelectorAll("#prelims-card .l-listing__item");
console.log("Main card length:", mainCard.length); console.log("Main card length:", mainCard.length);
@@ -95,6 +130,7 @@ async function getDetailsFromEventLink(url) {
mainCard = mainCard.map(convertLiToStr); mainCard = mainCard.map(convertLiToStr);
prelims = prelims.map(convertLiToStr); prelims = prelims.map(convertLiToStr);
} else { } else {
// Main card has not been announced, extract entire fight card
fightCard = root.querySelectorAll( fightCard = root.querySelectorAll(
".l-listing__group--bordered .l-listing__item" ".l-listing__group--bordered .l-listing__item"
); );
@@ -104,7 +140,9 @@ async function getDetailsFromEventLink(url) {
fightCard = fightCard.map(convertLiToStr); fightCard = fightCard.map(convertLiToStr);
} }
// Deentitize HTML entities
[name, location] = [decode(name), decode(location)]; [name, location] = [decode(name), decode(location)];
let details = { let details = {
name, name,
url, url,
@@ -120,10 +158,19 @@ async function getDetailsFromEventLink(url) {
} }
} }
/**
* Returns an array of details of recent and near-future UFC events
*
* @returns {Promise<Array<object>>} - A Promise that resolves with the array
* of details of recent and near-future UFC events
*/
async function getAllDetailedEvents() { async function getAllDetailedEvents() {
let events = []; let events = [];
try { try {
// Get the URLs of recent and near-future UFC events
events = await getEventLinks(); events = await getEventLinks();
// Convert each URL to the details of the corresponding UFC event
events = events.map(getDetailsFromEventLink); events = events.map(getDetailsFromEventLink);
events = await Promise.all(events); events = await Promise.all(events);
return events; return events;