User:Polygnotus/Scripts/CategoryToClipboard.js: Difference between revisions

Content deleted Content added
No edit summary
No edit summary
Line 67:
addTooltip(urlLabel, 'Include full Wikipedia URLs for each item in the export');
 
// Add checkbox for ignoring redirects
const ignoreRedirectsCheckbox = document.createElement('input');
ignoreRedirectsCheckbox.type = 'checkbox';
ignoreRedirectsCheckbox.id = 'ignoreRedirects';
ignoreRedirectsCheckbox.style.marginLeft = '15px';
const ignoreRedirectsLabel = document.createElement('label');
ignoreRedirectsLabel.htmlFor = 'ignoreRedirects';
ignoreRedirectsLabel.textContent = 'Ignore Redirects';
ignoreRedirectsLabel.style.marginLeft = '5px';
addTooltip(ignoreRedirectsLabel, 'Skip redirect pages and only include actual articles and content pages');
// Create status text
Line 91 ⟶ 81:
container.appendChild(urlCheckbox);
container.appendChild(urlLabel);
container.appendChild(ignoreRedirectsCheckbox);
container.appendChild(ignoreRedirectsLabel);
container.appendChild(statusText);
Line 312 ⟶ 300:
// Function to get all non-category members of a category
async function getNonCategoryMembers(categoryTitle, continueToken = null, ignoreRedirects = false) {
try {
// Base API URL for non-category members (exclude namespace 14, which is Category)
// Add maxlag parameter to be respectful of server load
let apiUrl = `https://en.wikipedia.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:${encodeURIComponent(categoryTitle)}&cmnamespace=0|1|2|3|4|5|6|7|8|9|10|11|12|13|15&cmlimit=max&maxlag=5&format=json&origin=*`;
// Add prop=info to get redirect information directly
if (ignoreRedirects) {
apiUrl += '&cmprop=title|ids&prop=info';
}
// Add continue token if provided
Line 337 ⟶ 320:
}
// Extract members and filter redirects if needed
letconst members = data.query.categorymembers.map(member => member.title);
if (ignoreRedirects && data.query.pages) {
// When ignoreRedirects is true and we have page info, filter out redirects
members = data.query.categorymembers
.filter(member => {
const pageInfo = data.query.pages[member.pageid];
return pageInfo && !pageInfo.hasOwnProperty('redirect');
})
.map(member => member.title);
} else {
// Normal case - just get titles
members = data.query.categorymembers.map(member => member.title);
}
const nextContinueToken = data.continue ? data.continue.cmcontinue : null;
Line 363 ⟶ 333:
// Function to get all members of a category, handling pagination
async function getAllCategoryMembers(categoryTitle, ignoreRedirects = false) {
let allMembers = [];
let continueToken = null;
Line 369 ⟶ 339:
do {
const { members, continueToken: nextToken } = await getNonCategoryMembers(categoryTitle, continueToken, ignoreRedirects);
allMembers = allMembers.concat(members);
continueToken = nextToken;
pagesProcessed++;
statusText.innerHTML = `Retrieved ${allMembers.length} items from "${categoryTitle}" (page ${pagesProcessed})${redirectText}...`;
const redirectText = ignoreRedirects ? ' (filtering redirects)' : '';
statusText.innerHTML = `Retrieved ${allMembers.length} items from "${categoryTitle}" (page ${pagesProcessed})${redirectText}...`;
} while (continueToken);
Line 435 ⟶ 404:
// Function to recursively get all items from a category and all its subcategories
async function getAllItemsRecursive(categoryTitle, ignoreRedirects = false) {
const visited = new Set();
const allItems = [];
Line 454 ⟶ 423:
totalCategories++;
statusText.innerHTML = `Getting items from "${currentCategory}" (processed ${totalCategories} categories, found ${allItems.length} items, queue: ${queue.length})${redirectText}...`;
const redirectText = ignoreRedirects ? ' (filtering redirects)' : '';
statusText.innerHTML = `Getting items from "${currentCategory}" (processed ${totalCategories} categories, found ${allItems.length} items, queue: ${queue.length})${redirectText}...`;
// Get items from current category
const currentItems = await getAllCategoryMembers(currentCategory, ignoreRedirects);
allItems.push(...currentItems);
Line 477 ⟶ 445:
// Handle "Copy Items" button click
copyItemsBtn.addEventListener('click', async () => {
statusText.innerHTML = `'Gathering items from this category via API${redirectText}...`';
const ignoreRedirects = ignoreRedirectsCheckbox.checked;
const redirectText = ignoreRedirects ? ' (filtering out redirects)' : '';
statusText.innerHTML = `Gathering items from this category via API${redirectText}...`;
try {
const items = await getAllCategoryMembers(categoryName, ignoreRedirects);
if (items.length === 0) {
Line 494 ⟶ 460:
const copySuccess = await copyToClipboardOrDownload(formattedText, categoryName);
if (copySuccess) {
const finalRedirectTextstatusText.innerHTML = ignoreRedirects ?`Successfully 'copied (excluding${items.length} redirects)'items :to ''clipboard.`;
statusText.innerHTML = `Successfully copied ${items.length} items to clipboard${finalRedirectText}.`;
}
} catch (error) {
Line 530 ⟶ 495:
// Handle "Copy All Items" button click
copyAllItemsBtn.addEventListener('click', async () => {
statusText.innerHTML = `'Gathering items from this category and all subcategories recursively via API${redirectText} (this may take a while)...`';
const ignoreRedirects = ignoreRedirectsCheckbox.checked;
const redirectText = ignoreRedirects ? ' (filtering out redirects)' : '';
statusText.innerHTML = `Gathering items from this category and all subcategories recursively via API${redirectText} (this may take a while)...`;
try {
Line 539 ⟶ 502:
// Get all items recursively
const { items: allItems, totalCategories } = await getAllItemsRecursive(categoryName, ignoreRedirects);
// Deduplicate items
Line 554 ⟶ 517:
const copySuccess = await copyToClipboardOrDownload(formattedText, categoryName + '_all_recursive');
if (copySuccess) {
statusText.innerHTML = `Successfully copied ${itemsuniqueItems.length} unique items to clipboard from ${finalRedirectTexttotalCategories} categories.`;
const finalRedirectText = ignoreRedirects ? ' (excluding redirects)' : '';
statusText.innerHTML = `Successfully copied ${uniqueItems.length} unique items to clipboard from ${totalCategories} categories${finalRedirectText}.`;
}
} catch (error) {