← back to Handbag Authentication
scripts/auto_register_apis.js
365 lines
#!/usr/bin/env node
/**
* AUTOMATIC API KEY REGISTRATION WITH PUPPETEER
* Automates registration for museum and government APIs
*
* Target APIs:
* 1. Europeana Fashion API
* 2. Rijksmuseum API
* 3. Harvard Art Museums API
* 4. Cooper Hewitt API
* 5. Smithsonian Open Access API
* 6. DPLA (Digital Public Library of America) API
*/
const puppeteer = require('puppeteer');
const fs = require('fs');
const path = require('path');
const OUTPUT_FILE = path.join(__dirname, '..', 'API_KEYS.json');
const LOG_FILE = path.join(__dirname, '..', 'handbag_data', 'api_registration_log.txt');
// User details for registration
const USER_INFO = {
firstName: 'Research',
lastName: 'Handbag',
email: process.env.REGISTRATION_EMAIL || 'your-email@example.com',
organization: 'Handbag Research Project',
purpose: 'Academic research on historical handbag and fashion accessory collections across European and Japanese museums',
website: 'https://github.com/handbag-research'
};
/**
* Logging utility
*/
function log(message, level = 'INFO') {
const timestamp = new Date().toISOString();
const logMessage = `[${timestamp}] [${level}] ${message}`;
console.log(logMessage);
fs.appendFileSync(LOG_FILE, logMessage + '\n');
}
/**
* Save API key to file
*/
function saveApiKey(apiName, apiKey) {
let keys = {};
if (fs.existsSync(OUTPUT_FILE)) {
keys = JSON.parse(fs.readFileSync(OUTPUT_FILE, 'utf8'));
}
keys[apiName] = {
key: apiKey,
registered_at: new Date().toISOString(),
status: 'active'
};
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(keys, null, 2));
log(`✅ Saved ${apiName} key to ${OUTPUT_FILE}`, 'SUCCESS');
}
/**
* Register for Europeana API
*/
async function registerEuropeana(page) {
const apiName = 'EUROPEANA_API_KEY';
log(`\n🇪🇺 Registering for Europeana API...`);
try {
await page.goto('https://pro.europeana.eu/page/get-api', { waitUntil: 'networkidle2' });
log('Filling registration form...');
// Fill form (selectors may need adjustment)
await page.waitForSelector('input[name="first_name"], input[name="firstName"], #first_name', { timeout: 10000 });
// Try different possible selectors
const firstNameSelectors = ['input[name="first_name"]', 'input[name="firstName"]', '#first_name'];
for (const selector of firstNameSelectors) {
try {
await page.type(selector, USER_INFO.firstName, { delay: 50 });
break;
} catch (e) {
continue;
}
}
await page.type('input[name="last_name"], input[name="lastName"], #last_name', USER_INFO.lastName, { delay: 50 });
await page.type('input[name="email"], #email', USER_INFO.email, { delay: 50 });
await page.type('input[name="company"], input[name="organization"], #company', USER_INFO.organization, { delay: 50 });
// Purpose/description
const purposeSelector = 'textarea[name="api_key_purpose"], textarea[name="purpose"], #purpose';
await page.waitForSelector(purposeSelector);
await page.type(purposeSelector, USER_INFO.purpose, { delay: 30 });
// Accept terms
const termsSelector = 'input[type="checkbox"][name="terms"]';
const termsCheckbox = await page.$(termsSelector);
if (termsCheckbox) {
await page.click(termsSelector);
}
log('Form filled. Ready to submit (MANUAL STEP REQUIRED)');
log('⚠️ Please review the form and click Submit button manually');
log('⚠️ Then check your email for the API key');
// Wait for user to submit
await page.waitForTimeout(5000);
log('📧 Check your email for Europeana API key', 'INFO');
log('Once received, add to .env: export EUROPEANA_API_KEY=your_key', 'INFO');
return { apiName, status: 'manual_completion_required', email: USER_INFO.email };
} catch (error) {
log(`Error with Europeana registration: ${error.message}`, 'ERROR');
return { apiName, status: 'error', error: error.message };
}
}
/**
* Register for data.gov API key (for Smithsonian)
*/
async function registerDataGov(page) {
const apiName = 'SMITHSONIAN_API_KEY';
log(`\n🇺🇸 Registering for data.gov API (Smithsonian)...`);
try {
await page.goto('https://api.data.gov/signup/', { waitUntil: 'networkidle2' });
log('Filling data.gov registration form...');
await page.waitForSelector('input[name="first_name"]', { timeout: 10000 });
await page.type('input[name="first_name"]', USER_INFO.firstName, { delay: 50 });
await page.type('input[name="last_name"]', USER_INFO.lastName, { delay: 50 });
await page.type('input[name="email"]', USER_INFO.email, { delay: 50 });
// Website/purpose
const websiteSelector = 'input[name="website"]';
const websiteInput = await page.$(websiteSelector);
if (websiteInput) {
await page.type(websiteSelector, USER_INFO.website, { delay: 50 });
}
// Use purpose
const purposeSelector = 'textarea[name="use_description"]';
const purposeTextarea = await page.$(purposeSelector);
if (purposeTextarea) {
await page.type(purposeSelector, USER_INFO.purpose, { delay: 30 });
}
// Terms
const termsSelector = 'input[type="checkbox"][name="terms_and_conditions"]';
const termsCheckbox = await page.$(termsSelector);
if (termsCheckbox) {
await page.click(termsSelector);
}
log('data.gov form filled. Ready to submit (MANUAL STEP REQUIRED)');
log('⚠️ Please review and click Submit button manually');
await page.waitForTimeout(5000);
log('📧 Check your email for data.gov API key', 'INFO');
log('Use this key for Smithsonian API access', 'INFO');
return { apiName, status: 'manual_completion_required', email: USER_INFO.email };
} catch (error) {
log(`Error with data.gov registration: ${error.message}`, 'ERROR');
return { apiName, status: 'error', error: error.message };
}
}
/**
* Register for DPLA API
*/
async function registerDPLA(page) {
const apiName = 'DPLA_API_KEY';
log(`\n📚 Registering for DPLA API...`);
try {
await page.goto('https://pro.dp.la/developers/api-key-request', { waitUntil: 'networkidle2' });
log('Filling DPLA registration form...');
await page.waitForSelector('input[name="name"], input[name="full_name"]', { timeout: 10000 });
// Full name
const fullName = `${USER_INFO.firstName} ${USER_INFO.lastName}`;
await page.type('input[name="name"], input[name="full_name"]', fullName, { delay: 50 });
// Email
await page.type('input[name="email"]', USER_INFO.email, { delay: 50 });
// Purpose
const purposeSelector = 'textarea[name="use_case"], textarea[name="purpose"]';
await page.type(purposeSelector, USER_INFO.purpose, { delay: 30 });
log('DPLA form filled. Ready to submit (MANUAL STEP REQUIRED)');
log('⚠️ Please review and submit manually');
await page.waitForTimeout(5000);
log('📧 API key should be emailed immediately', 'INFO');
return { apiName, status: 'manual_completion_required', email: USER_INFO.email };
} catch (error) {
log(`Error with DPLA registration: ${error.message}`, 'ERROR');
return { apiName, status: 'error', error: error.message };
}
}
/**
* Open Rijksmuseum API registration page
*/
async function registerRijksmuseum(page) {
const apiName = 'RIJKSMUSEUM_API_KEY';
log(`\n🇳🇱 Opening Rijksmuseum API registration...`);
try {
await page.goto('https://data.rijksmuseum.nl/', { waitUntil: 'networkidle2' });
log('Rijksmuseum page loaded');
log('⚠️ Please create account manually and request API key');
log('⚠️ API key is usually provided immediately after account creation');
await page.waitForTimeout(5000);
return { apiName, status: 'manual_registration_required', url: 'https://data.rijksmuseum.nl/' };
} catch (error) {
log(`Error opening Rijksmuseum: ${error.message}`, 'ERROR');
return { apiName, status: 'error', error: error.message };
}
}
/**
* Open Harvard Art Museums API page
*/
async function registerHarvard(page) {
const apiName = 'HARVARD_API_KEY';
log(`\n🎓 Opening Harvard Art Museums API registration...`);
try {
await page.goto('https://harvardartmuseums.org/collections/api', { waitUntil: 'networkidle2' });
log('Harvard API page loaded');
log('⚠️ Click "Get a Key" and sign in with Google/Microsoft');
log('⚠️ API key provided immediately after authentication');
await page.waitForTimeout(5000);
return { apiName, status: 'manual_registration_required', url: 'https://harvardartmuseums.org/collections/api' };
} catch (error) {
log(`Error opening Harvard: ${error.message}`, 'ERROR');
return { apiName, status: 'error', error: error.message };
}
}
/**
* Main execution
*/
async function main() {
log('='.repeat(80));
log('🤖 AUTOMATIC API KEY REGISTRATION WITH PUPPETEER');
log('='.repeat(80));
// Check if email is configured
if (USER_INFO.email === 'your-email@example.com') {
log('⚠️ ERROR: Please set REGISTRATION_EMAIL environment variable', 'ERROR');
log('Usage: REGISTRATION_EMAIL=your-email@example.com node scripts/auto_register_apis.js', 'INFO');
process.exit(1);
}
log(`Registration email: ${USER_INFO.email}`);
log(`Organization: ${USER_INFO.organization}`);
const browser = await puppeteer.launch({
headless: false, // Show browser for manual interaction
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const results = [];
try {
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
// Register for each API
log('\n📋 Starting registration process...\n');
// Europeana
const europeanaResult = await registerEuropeana(page);
results.push(europeanaResult);
await page.waitForTimeout(3000);
// data.gov (Smithsonian)
const dataGovResult = await registerDataGov(page);
results.push(dataGovResult);
await page.waitForTimeout(3000);
// DPLA
const dplaResult = await registerDPLA(page);
results.push(dplaResult);
await page.waitForTimeout(3000);
// Rijksmuseum
const rijksResult = await registerRijksmuseum(page);
results.push(rijksResult);
await page.waitForTimeout(3000);
// Harvard
const harvardResult = await registerHarvard(page);
results.push(harvardResult);
// Summary
log('\n' + '='.repeat(80));
log('📊 REGISTRATION SUMMARY');
log('='.repeat(80));
results.forEach(result => {
log(`${result.apiName}: ${result.status}`);
});
log('\n📧 NEXT STEPS:');
log('1. Check your email for API keys');
log('2. Add keys to .env file:');
log(' export EUROPEANA_API_KEY=your_key');
log(' export SMITHSONIAN_API_KEY=your_key');
log(' export DPLA_API_KEY=your_key');
log(' export RIJKSMUSEUM_API_KEY=your_key');
log(' export HARVARD_API_KEY=your_key');
log('\n3. Run scrapers:');
log(' node scripts/mega_handbag_scraper.js');
log(' node scripts/us_government_bigquery_scraper.js');
log('\n⏳ Keeping browser open for manual completion...');
log('Press Ctrl+C when done');
// Keep browser open for manual steps
await new Promise(() => {});
} catch (error) {
log(`FATAL ERROR: ${error.message}`, 'ERROR');
throw error;
} finally {
// Don't close browser automatically
// await browser.close();
}
}
// Run if called directly
if (require.main === module) {
main().catch(error => {
console.error('FATAL ERROR:', error);
process.exit(1);
});
}
module.exports = { main };