const fs = require('fs'); const path = require('path'); const csvParser = require('csv-parser'); const koillectionBaseUrl = 'https://koillection.nelson-household.com/api'; // Verify this URL const authenticationUrl = `${koillectionBaseUrl}/authentication_token`; // URL to obtain JWT const imagesDir = path.join(__dirname, 'images'); // Use __dirname for correct path // Define mapping of collection names to their corresponding CSV files const collectionsMapping = { 'Perfect Order': './ME03PerfectOrderProductsAndPrices.csv', }; const createJWTToken = async (username, password) => { try { const response = await fetch(authenticationUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username, password }), }); if (!response.ok) { throw new Error(`Failed to obtain JWT token: ${response.status} - ${response.statusText}`); } const data = await response.json(); console.log(`JWT Token obtained: ${data.token}`); return data.token; } catch (error) { console.error(`Error obtaining JWT token:`, error); throw error; // Re-throw to be caught in other functions } }; const createCollectionIfNotExists = async (name, parentCollectionId, token) => { try { const url = `${koillectionBaseUrl}/collections`; const response = await fetch(url, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ title: name, visibility: 'public', parent: `/api/collections/${parentCollectionId}` }), }); if (!response.ok) { throw new Error(`Failed to create collection "${name}": ${response.status} - ${response.statusText} - ${JSON.stringify(await response.json())}`); } const data = await response.json(); console.log(`Successfully created collection "${name}" with ID: ${data.id}`); return data.id; } catch (error) { console.error(`Error creating collection ${name} from CSV:`, error); throw error; } }; const createItem = async (payload, token) => { try { const response = await fetch(`${koillectionBaseUrl}/items`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }); if (!response.ok) { throw new Error(`Failed to create item: ${response.status} - ${await response.text()}`); } const createdItem = await response.json(); return createdItem; } catch (error) { console.error('Error creating item:', error); throw error; } }; async function downloadTcgImage(itemId, imageUrl) { try { // 1. Fetch the image data using fetch const response = await fetch(imageUrl, { method: 'GET', // Use GET for image retrieval responseType: 'stream' // Important for streaming the image }); if (!response.ok) { throw new Error(`Failed to fetch image: ${response.statusText}`); } // 2. Download the image using your existing logic const dest = path.join(imagesDir, `${itemId}_${imageUrl.split('/').pop()}`); await new Promise((resolve, reject) => { response.body.pipe(fs.createWriteStream(dest)); response.body.on('error', reject); (async () => { try { await new Promise((resolve, reject) => { response.body.on('finish', () => resolve()); }); } catch (error) { reject(error); } })(); }); console.log(`Image saved to ${dest}`); return { success: true, destination: dest }; } catch (error) { console.error('Error applying image:', error); throw error; } } const applyImageToItem = async (itemId, localImagePath, token) => { try { const response = await fetch(`${koillectionBaseUrl}/items/${itemId}/image`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'multipart/form-data', // Important for file uploads }, body: new FormData({ append: 'image', value: new Blob([fs.readFileSync(localImagePath)]), // Use fs.readFileSync to read the local file }, 'image.jpg') }); if (!response.ok) { const errorData = await response.json(); throw new Error(`HTTP error! Status: ${response.status}, Error: ${JSON.stringify(errorData)}`); } const data = await response.json(); return data; // Returns the item with the new image } catch (error) { console.error('Error applying image:', error); throw error; // Re-throw for handling in the caller } }; const parseCsv = async (collectionId, csvFilePath, token) => { try { const rows = []; fs.createReadStream(csvFilePath) .pipe(csvParser()) .on('data', (row) => rows.push(row)) .on('end', async () => { rows.map(async (row) => { //console.log(`Here is the row wer are on: ${JSON.stringify(row, null, 2)}`); const payload = { name: row.name, collection: `/api/collections/${collectionId}`, visibility: 'public', }; try { const createdItem = await createItem(payload, token); console.log(`Created item: ${createdItem.name}`); const imageObj = await downloadTcgImage(createdItem.id, row.imageUrl); const image = applyImageToItem(createdItem.id, imageObj.destination, token); console.log(`Applied image to item: ${createdItem.name}`); } catch (itemError) { console.error(`Error creating item for row ${row.name}:`, itemError); } }); }); } catch (error) { console.error(`Error creating collection ${name} from CSV:`, error); } } const createCollectionFromCSV = async (name, csvFilePath) => { const token = await createJWTToken('bigassdragon', 'd7Bis4Y4EUhfMf'); const joeCollectionId = await createCollectionIfNotExists(name, '019dc310-a130-799e-8c0d-db90774b7b77', token); const tylerCollectionId = await createCollectionIfNotExists(name, '019dc310-d175-7e59-b465-c8e684ee7186', token); await parseCsv(joeCollectionId, csvFilePath, token); await parseCsv(tylerCollectionId, csvFilePath, token); }; // Main execution async function main() { for (const collectionName in collectionsMapping) { try { await createCollectionFromCSV(collectionName, collectionsMapping[collectionName]); } catch (error) { console.error(`Error processing collection - ${collectionName}:`, error); } } } main();