← 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 };