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

Content deleted Content added
No edit summary
No edit summary
Line 1:
const handleSearchAction = async function() {
// Wikipedia List Generator - Special:BlankPage/Listgen
const query = $('#search-input').val().trim();
if (!query) {
updateStatus('Please enter a search query.');
return;
}
setOperationState(true);
OPERATION_STATE.currentOperation = 'search';
const includeUrls = $('#include-urls').is(':checked');
const statusCallback = (msg) => updateStatus(msg);
try {
const items = await fetchSearchResults(query, statusCallback);
if (OPERATION_STATE.shouldStop) {
updateStatus('Operation stopped by user.');
return;// Wikipedia List Generator - Special:BlankPage/Listgen
// Universal Wikipedia List Copier adapted for dedicated blank page interface
 
Line 18 ⟶ 36:
BASE_URL: 'https://en.wikipedia.org',
API_URL: 'https://en.wikipedia.org/w/api.php'
};
 
// Global state for pause/stop functionality
const OPERATION_STATE = {
isPaused: false,
shouldStop: false,
currentOperation: null
};
 
Line 83 ⟶ 108:
 
async function makeApiRequest(url, retryCount = 0) {
// Check for stop signal
await new Promise(resolve => setTimeout(resolve, CONFIG.API_DELAY));
if (OPERATION_STATE.shouldStop) {
throw new Error('Operation stopped by user');
}
// Handle pause
while (OPERATION_STATE.isPaused && !OPERATION_STATE.shouldStop) {
await new Promise(resolve => setTimeout(resolve, 100));
}
// Use dynamic delay from UI
const delay = parseInt($('#delay-input').val()) || CONFIG.API_DELAY;
await new Promise(resolve => setTimeout(resolve, delay));
try {
Line 114 ⟶ 151:
return data;
} catch (error) {
if (retryCount < CONFIG.MAX_RETRIES && !OPERATION_STATE.shouldStop) {
await new Promise(resolve => setTimeout(resolve, 1000));
return makeApiRequest(url, retryCount + 1);
Line 129 ⟶ 166:
do {
// Check for stop signal
if (OPERATION_STATE.shouldStop) {
throw new Error('Operation stopped by user');
}
const url = apiConfig.buildUrl(continueToken);
statusCallback(`${apiConfig.progressMessage} (page ${pagesProcessed + 1})...`);
Line 140 ⟶ 182:
statusCallback(`Retrieved ${allItems.length} ${apiConfig.itemType} (page ${pagesProcessed})...`);
} while (continueToken && !OPERATION_STATE.shouldStop);
return allItems;
Line 284 ⟶ 326:
let totalCategories = 0;
while (queue.length > 0 && !OPERATION_STATE.shouldStop) {
const currentCategory = queue.shift();
const categoryKey = `Category:${currentCategory}`;
Line 310 ⟶ 352:
// ===== UI SETUP =====
 
functionconst setupListGeneratorInterface = function() {
const content = $('#mw-content-text');
content.html(`
Line 320 ⟶ 362:
<div id="listgen-tabs" style="margin-bottom: 20px;">
<button class="listgen-tab active" data-tab="category">CategoriesCategory Tools</button>
<button class="listgen-tab" data-tab="backlinks">WhatlinkshereBacklinks</button>
<button class="listgen-tab" data-tab="prefix">Prefix Search</button>
<button class="listgen-tab" data-tab="search">Search Results</button>
Line 363 ⟶ 405:
<h3>Prefix Search Tools</h3>
<div class="input-group">
<label for="prefix-input">PrefixPage title with namespace prefix (if any):</label>
<input type="text" id="prefix-input" placeholder="e.g., List of, User:Jimbo, Template:Infobox" style="width: 300px400px; padding: 5px;">
</div style="font-size: 12px; color: #666; margin-top: 5px;">
Examples: "List of" (mainspace), "User:Jimbo" (user namespace), "Template:Infobox" (template namespace)
<div class="input-group">
<label for="namespace-select">Namespace:</labeldiv>
<select id="namespace-select" style="padding: 5px;">
<option value="0">Main (0)</option>
<option value="1">Talk (1)</option>
<option value="2">User (2)</option>
<option value="4">Wikipedia (4)</option>
<option value="6">File (6)</option>
<option value="10">Template (10)</option>
<option value="14">Category (14)</option>
</select>
</div>
<div class="button-group">
Line 398 ⟶ 431:
<div class="options-section" style="margin: 20px 0; padding: 15px; background: #f8f9fa; border: 1px solid #a2a9b1; border-radius: 3px;">
<labeldiv style="margin-bottom: 15px;">
<label>
<input type="checkbox" id="include-urls"> Include URLs
</label>
<span style="margin-left: 10px; color: #666; font-size: 12px;">Check to include full Wikipedia URLs for each item</span>
</div>
<div style="margin-bottom: 15px;">
<label for="delay-input" style="display: inline-block; width: 200px;">API Request Delay (ms):</label>
<input type="number" id="delay-input" value="500" min="100" max="5000" step="100" style="width: 100px; padding: 3px;">
<span style="margin-left: 10px; color: #666; font-size: 12px;">Time to wait between API requests (100-5000ms)</span>
</div>
<div class="control-buttons">
<button id="pause-btn" style="background: #ff9500; color: white; border: none; padding: 8px 15px; border-radius: 3px; margin-right: 10px;" disabled>⏸️ Pause</button>
<button id="stop-btn" style="background: #d33; color: white; border: none; padding: 8px 15px; border-radius: 3px;" disabled>⏹️ Stop</button>
</div>
</div>
Line 466 ⟶ 512:
setupEventHandlers();
};
 
functionconst setupEventHandlers = function() {
// Tab switching
$('.listgen-tab').on('click', function() {
Line 492 ⟶ 538:
$('#prefix-search').on('click', handlePrefixAction);
$('#search-results').on('click', handleSearchAction);
}
// Control button handlers
$('#pause-btn').on('click', handlePauseResume);
$('#stop-btn').on('click', handleStop);
};
 
// ===== CONTROL FUNCTIONS =====
 
const setOperationState = function(isRunning) {
if (isRunning) {
OPERATION_STATE.shouldStop = false;
OPERATION_STATE.isPaused = false;
$('#pause-btn').prop('disabled', false).text('⏸️ Pause');
$('#stop-btn').prop('disabled', false);
$('.button-group button').prop('disabled', true);
} else {
OPERATION_STATE.shouldStop = false;
OPERATION_STATE.isPaused = false;
OPERATION_STATE.currentOperation = null;
$('#pause-btn').prop('disabled', true).text('⏸️ Pause');
$('#stop-btn').prop('disabled', true);
$('.button-group button').prop('disabled', false);
}
};
 
const handlePauseResume = function() {
if (OPERATION_STATE.isPaused) {
OPERATION_STATE.isPaused = false;
$('#pause-btn').text('⏸️ Pause');
updateStatus('Operation resumed...');
} else {
OPERATION_STATE.isPaused = true;
$('#pause-btn').text('▶️ Resume');
updateStatus('Operation paused. Click Resume to continue.');
}
};
 
const handleStop = function() {
OPERATION_STATE.shouldStop = true;
OPERATION_STATE.isPaused = false;
updateStatus('Stopping operation...');
setOperationState(false);
};
 
// ===== ACTION HANDLERS =====
 
const handleCategoryAction = async function handleCategoryAction(action) {
const categoryName = $('#category-input').val().trim();
if (!categoryName) {
Line 502 ⟶ 590:
return;
}
setOperationState(true);
OPERATION_STATE.currentOperation = `category-${action}`;
const includeUrls = $('#include-urls').is(':checked');
Line 539 ⟶ 630:
filename = `${categoryName}_both_recursive`;
break;
}
if (OPERATION_STATE.shouldStop) {
updateStatus('Operation stopped by user.');
return;
}
Line 553 ⟶ 649:
}
} catch (error) {
updateStatus(`Error:if ${(error.message}` === 'Operation stopped by user'); {
updateStatus('Operation stopped by user.');
} else {
updateStatus(`Error: ${error.message}`);
}
} finally {
setOperationState(false);
}
};;;;
}
 
const handleBacklinksAction = async function handleBacklinksAction(type) {
const targetTitle = $('#backlinks-input').val().trim();
if (!targetTitle) {
Line 563 ⟶ 665:
return;
}
setOperationState(true);
OPERATION_STATE.currentOperation = `backlinks-${type}`;
const includeUrls = $('#include-urls').is(':checked');
Line 582 ⟶ 687:
case 'non-mainspace':
const allBacklinks = await fetchBacklinks(targetTitle, null, statusCallback);
if (OPERATION_STATE.shouldStop) return;
updateStatus('Filtering out mainspace backlinks...');
const mainspaceBacklinks = await fetchBacklinks(targetTitle, '0', statusCallback);
Line 588 ⟶ 694:
filename = 'non_mainspace_backlinks';
break;
}
if (OPERATION_STATE.shouldStop) {
updateStatus('Operation stopped by user.');
return;
}
Line 602 ⟶ 713:
}
} catch (error) {
updateStatus(`Error:if ${(error.message}` === 'Operation stopped by user'); {
updateStatus('Operation stopped by user.');
} else {
updateStatus(`Error: ${error.message}`);
}
} finally {
setOperationState(false);
}
}
 
const handlePrefixAction = async function handlePrefixAction() {
const prefixfullInput = $('#prefix-input').val().trim();
const namespace = $('#namespace-select').val();
if (!prefixfullInput) {
updateStatus('Please enter a prefix or page title.');
return;
}
setOperationState(true);
OPERATION_STATE.currentOperation = 'prefix-search';
// Parse namespace and prefix from input
let namespace = '0'; // Default to mainspace
let prefix = fullInput;
// Check if input contains namespace prefix
if (fullInput.includes(':')) {
const [namespaceName, actualPrefix] = fullInput.split(':', 2);
const namespaceMap = {
'User': '2',
'Wikipedia': '4',
'File': '6',
'Image': '6', // Alias for File
'MediaWiki': '8',
'Template': '10',
'Help': '12',
'Category': '14',
'Portal': '100',
'Draft': '118',
'Talk': '1',
'User talk': '3',
'Wikipedia talk': '5',
'File talk': '7',
'MediaWiki talk': '9',
'Template talk': '11',
'Help talk': '13',
'Category talk': '15'
};
if (namespaceMap[namespaceName]) {
namespace = namespaceMap[namespaceName];
prefix = actualPrefix || ''; // Handle cases like "User:" with no prefix after
}
// If not a recognized namespace, treat the whole input as prefix in mainspace
}
Line 620 ⟶ 774:
try {
const items = await fetchPrefixPages(prefix, namespace, statusCallback);
if (OPERATION_STATE.shouldStop) {
updateStatus('Operation stopped by user.');
return;
}
if (items.length === 0) {
updateStatus(`No pages found with prefix "${prefixfullInput}" in namespace ${namespace}.`);
return;
}
const filename = `prefix_${prefixfullInput.replace(/[^a-zA-Z0-9]/g, '_')}`;
const formattedText = formatItems(items, includeUrls);
const copySuccess = await copyToClipboardOrDownload(formattedText, filename, $('#status-section'));
Line 634 ⟶ 793:
}
} catch (error) {
updateStatus(`Error:if ${(error.message}` === 'Operation stopped by user'); {
updateStatus('Operation stopped by user.');
} else {
updateStatus(`Error: ${error.message}`);
}
} finally {
setOperationState(false);
}
}
 
const handleSearchAction = async function handleSearchAction() {
const query = $('#search-input').val().trim();
if (!query) {
Line 644 ⟶ 809:
return;
}
setOperationState(true);
OPERATION_STATE.currentOperation = 'search';
const includeUrls = $('#include-urls').is(':checked');
Line 650 ⟶ 818:
try {
const items = await fetchSearchResults(query, statusCallback);
if (OPERATION_STATE.shouldStop) {
updateStatus('Operation stopped by user.');
return;
}
if (items.length === 0) {
Line 664 ⟶ 837:
}
} catch (error) {
updateStatus(`Error:if ${(error.message}` === 'Operation stopped by user'); {
updateStatus('Operation stopped by user.');
} else {
updateStatus(`Error: ${error.message}`);
}
} finally {
setOperationState(false);
}
}
Line 674 ⟶ 853:
const queue = [`Category:${categoryTitle}`];
while (queue.length > 0 && !OPERATION_STATE.shouldStop) {
const currentCategory = queue.shift();
Line 703 ⟶ 882:
let totalCategories = 0;
while (queue.length > 0 && !OPERATION_STATE.shouldStop) {
const currentCategory = queue.shift();
const categoryKey = `Category:${currentCategory}`;
Line 731 ⟶ 910:
}
 
functionconst updateStatus = function(message) {
$('#status-text').html(message);
};
 
console.log('Wikipedia List Generator loaded successfully!');