Skip to content

Instantly share code, notes, and snippets.

@MarketingPip
Created March 15, 2025 02:12
Show Gist options
  • Save MarketingPip/e7723b2d6cac3fe674fbd691239dcbb4 to your computer and use it in GitHub Desktop.
Save MarketingPip/e7723b2d6cac3fe674fbd691239dcbb4 to your computer and use it in GitHub Desktop.
import wtf from "https://esm.sh/wtf_wikipedia";
import wtf_plugin from "https://esm.sh/wtf-plugin-api";
wtf.extend(wtf_plugin);
class CategoryPageBuilder {
constructor(category, maxDepth) {
this.category = category;
this.maxDepth = maxDepth;
this.results = [];
this.subcategoryResults = {}; // To store pages by subcategory titles
}
// Recursive function to fetch category pages
async getCategoryPagesWithDepth(category, depth, maxDepth) {
if (depth > maxDepth) return [];
let results = [];
let pages = await wtf.getCategoryPages(category);
console.log(pages)
let pageResults = pages.filter(item => item.type === "page");
let subcategories = pages.filter(item => item.type === "subcat");
// Add pages to the results
results.push(...pageResults);
// Recursively fetch subcategories and their pages
let subcategoryPromises = subcategories.map(subcat =>
this.getCategoryPagesWithDepth(subcat.title, depth + 1, maxDepth)
);
let subcategoryResults = await Promise.all(subcategoryPromises);
subcategoryResults.flat().forEach(item => results.push(item));
// Store subcategories and their respective pages
for (let subcat of subcategories) {
this.subcategoryResults[subcat.title] = [];
}
// Fetch pages for subcategories and correctly associate them
for (let subcat of subcategories) {
let subcategoryPages = await wtf.getCategoryPages(subcat.title);
let subcategoryEvents = subcategoryPages.filter(page => page.type === "page");
this.subcategoryResults[subcat.title].push(...subcategoryEvents);
}
if( this.subcategoryResults?.length === 0 || this.subcategoryResults != null){
this.subcategoryResults["Catergory:uncategorized"] = pageResults
}
return results;
}
// Start the recursive fetching
async build() {
this.results = await this.getCategoryPagesWithDepth(this.category, 1, this.maxDepth);
return this; // Return the instance to allow chaining
}
// Return the results as JSON
json() {
return JSON.stringify(this.results, null, 2);
}
// Return the results in a prettified format with subcategories organized
prettify() {
let organized = {
categoryTitle: this.category.split(':')[1], // Remove "Category:" prefix
subcategories: []
};
// Organize the subcategories and their events
for (let title in this.subcategoryResults) {
organized.subcategories.push({
[title.split(':')[1]]: { // Key is subcategory title
events: this.subcategoryResults[title] // Subcategory pages
}
});
}
return JSON.stringify(organized, null, 2);
}
}
// Main function to initiate the builder and process the request
async function getAllCategoryPages(category, maxDepth = 5) {
const builder = new CategoryPageBuilder(category, maxDepth);
await builder.build(); // Start the process of fetching and building results
return builder; // Return the builder instance for chaining methods
}
async function getCrimes(year, country) {
// Validate inputs
if (!Number.isInteger(year)) {
throw new Error("Year must be an integer.");
}
if (typeof country !== "string" || country.trim() === "") {
throw new Error("Country must be a non-empty string.");
}
// Format the category string
let category = `Category:${year}_crimes_in_${country.replace(/\s+/g, "_")}`;
// Create a CategoryPages instance
let categoryFetcher = await getAllCategoryPages(category, 3)
// Return both raw JSON and prettified results
return categoryFetcher
}
// Usage
// Australia
// the United States
// Canada
// Germany
// Europe
// Poland
// the United Kingdom
// China
// Asia
getCrimes(2007, "Canada").then(result => {
console.log(result.json()); // Output raw JSON
console.log(result.prettify()); // Output prettified structure
});
//
@MarketingPip
Copy link
Author

MarketingPip commented Mar 26, 2025

Sports fetcher.

import wtf from "https://esm.sh/wtf_wikipedia";
import wtf_plugin from "https://esm.sh/wtf-plugin-api";

wtf.extend(wtf_plugin);

class CategoryPageBuilder {
  constructor(category, maxDepth) {
    this.category = category;
    this.maxDepth = maxDepth;
    this.results = [];
    this.subcategoryResults = {};  // Store pages by subcategory titles
  }

  // Recursive function to fetch category pages
  async getCategoryPagesWithDepth(category, depth, maxDepth) {
    if (depth > maxDepth) return [];

    let results = [];
    let pages;

    try {
      pages = await wtf.getCategoryPages(category);
    } catch (error) {
      console.error(`Failed to fetch pages for ${category}:`, error);
      return [];
    }

    if (!pages || pages.length === 0) {
      console.warn(`No pages found for ${category}`);
      return [];
    }

    console.log(`Fetched ${pages.length} pages from ${category}`);

    let pageResults = pages.filter(item => item.type === "page");
    let subcategories = pages.filter(item => item.type === "subcat");

    results.push(...pageResults);

    let subcategoryPromises = subcategories.map(subcat =>
      this.getCategoryPagesWithDepth(subcat.title, depth + 1, maxDepth)
    );

    let subcategoryResults = await Promise.all(subcategoryPromises);
    subcategoryResults.flat().forEach(item => results.push(item));

    for (let subcat of subcategories) {
      this.subcategoryResults[subcat.title] = [];
    }

    for (let subcat of subcategories) {
      let subcategoryPages = await wtf.getCategoryPages(subcat.title);
      let subcategoryEvents = subcategoryPages.filter(page => page.type === "page");
      this.subcategoryResults[subcat.title].push(...subcategoryEvents);
    }

    if (!Object.keys(this.subcategoryResults).length) {
      this.subcategoryResults["Category:uncategorized"] = pageResults;
    }

    return results;
  }

  async build() {
    this.results = await this.getCategoryPagesWithDepth(this.category, 1, this.maxDepth);
    return this;
  }

  json() {
    return JSON.stringify(this.results, null, 2);
  }

  prettify() {
    let organized = {
      categoryTitle: this.category.split(':')[1],
      totalPages: this.results.length,
      subcategories: []
    };

    for (let title in this.subcategoryResults) {
      organized.subcategories.push({
        [title.split(':')[1]]: {
          events: this.subcategoryResults[title]
        }
      });
    }

    return JSON.stringify(organized, null, 2);
  }
}

// Main function to initiate the builder and process the request
async function getAllCategoryPages(category, maxDepth = 3) {
  const builder = new CategoryPageBuilder(category, maxDepth);
  await builder.build();
  return builder;
}

async function getSportsCategory(year, region) {
  if (!Number.isInteger(year)) {
    throw new Error("Year must be an integer.");
  }

  if (typeof region !== "string" || region.trim() === "") {
    throw new Error("Region must be a non-empty string.");
  }

  let category = `Category:${year}_in_sports_in_${region.replace(/\s+/g, "_")}`;

  console.log(`Fetching data for: ${category}`);
  
  let categoryFetcher = await getAllCategoryPages(category, 3);

  return categoryFetcher;
}

// Usage Example
getSportsCategory(2008, "Ontario").then(result => {
  console.log("\nRaw JSON:\n", result.json());
  console.log("\nPrettified Output:\n", result.prettify());
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment