Working ISBN scan
This commit is contained in:
108
index.js
108
index.js
@@ -18,6 +18,7 @@ const credentials = { key: privateKey, cert: certificate };
|
|||||||
// Middleware to parse JSON bodies
|
// Middleware to parse JSON bodies
|
||||||
app.use(express.json()); // Use built-in body-parser for JSON
|
app.use(express.json()); // Use built-in body-parser for JSON
|
||||||
|
|
||||||
|
// Set up the SQLite database
|
||||||
// Set up the SQLite database
|
// Set up the SQLite database
|
||||||
const db = new sqlite3.Database('./books.db', (err) => {
|
const db = new sqlite3.Database('./books.db', (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -31,15 +32,26 @@ const db = new sqlite3.Database('./books.db', (err) => {
|
|||||||
title TEXT,
|
title TEXT,
|
||||||
authors TEXT,
|
authors TEXT,
|
||||||
publishedDate TEXT,
|
publishedDate TEXT,
|
||||||
description TEXT
|
description TEXT,
|
||||||
|
url TEXT,
|
||||||
|
number_of_pages INTEGER,
|
||||||
|
identifiers TEXT,
|
||||||
|
publishers TEXT,
|
||||||
|
subjects TEXT,
|
||||||
|
notes TEXT,
|
||||||
|
cover_small TEXT,
|
||||||
|
cover_medium TEXT,
|
||||||
|
cover_large TEXT
|
||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Serve static files from the 'public' directory
|
// Serve static files from the 'public' directory
|
||||||
app.use(express.static(path.join(__dirname, 'public')));
|
app.use(express.static(path.join(__dirname, 'public')));
|
||||||
|
|
||||||
|
// Endpoint to fetch book details by ISBN
|
||||||
// Endpoint to fetch book details by ISBN
|
// Endpoint to fetch book details by ISBN
|
||||||
app.get('/book/:isbn', async (req, res) => {
|
app.get('/book/:isbn', async (req, res) => {
|
||||||
const { isbn } = req.params;
|
const { isbn } = req.params;
|
||||||
@@ -52,7 +64,6 @@ app.get('/book/:isbn', async (req, res) => {
|
|||||||
|
|
||||||
if (bookData) {
|
if (bookData) {
|
||||||
console.log('Book data found in Open Library');
|
console.log('Book data found in Open Library');
|
||||||
console.log(bookData);
|
|
||||||
res.json(formatOpenLibraryData(bookData));
|
res.json(formatOpenLibraryData(bookData));
|
||||||
} else {
|
} else {
|
||||||
// Fallback to Internet Archive if no data from Open Library
|
// Fallback to Internet Archive if no data from Open Library
|
||||||
@@ -72,23 +83,78 @@ app.get('/book/:isbn', async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Endpoint to store book in the database
|
||||||
|
// Endpoint to store book in the database
|
||||||
// Endpoint to store book in the database
|
// Endpoint to store book in the database
|
||||||
app.post('/store-book', (req, res) => {
|
app.post('/store-book', (req, res) => {
|
||||||
const { isbn, title, authors, publishedDate, description } = req.body;
|
const {
|
||||||
|
isbn, title, authors, publishedDate, description, url,
|
||||||
|
number_of_pages, identifiers, publishers, subjects,
|
||||||
|
notes, cover_small, cover_medium, cover_large
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
const query = `INSERT INTO books (isbn, title, authors, publishedDate, description) VALUES (?, ?, ?, ?, ?)`;
|
// Check if a book with the same ISBN already exists
|
||||||
const params = [isbn, title, authors ? authors.join(', ') : '', publishedDate, description || ''];
|
const checkQuery = `SELECT * FROM books WHERE isbn = ?`;
|
||||||
|
db.get(checkQuery, [isbn], (err, row) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error checking for existing book:', err);
|
||||||
|
return res.status(500).json({ error: 'Failed to check for existing book' });
|
||||||
|
}
|
||||||
|
|
||||||
db.run(query, params, function (err) {
|
if (row) {
|
||||||
|
// Book already exists, update the existing record
|
||||||
|
const updateQuery = `
|
||||||
|
UPDATE books
|
||||||
|
SET title = ?, authors = ?, publishedDate = ?, description = ?, url = ?,
|
||||||
|
number_of_pages = ?, identifiers = ?, publishers = ?, subjects = ?,
|
||||||
|
notes = ?, cover_small = ?, cover_medium = ?, cover_large = ?
|
||||||
|
WHERE isbn = ?
|
||||||
|
`;
|
||||||
|
|
||||||
|
const updateParams = [
|
||||||
|
title, authors ? authors.join(', ') : '', publishedDate, description || '',
|
||||||
|
url, number_of_pages, identifiers, publishers, subjects,
|
||||||
|
notes, cover_small, cover_medium, cover_large, isbn
|
||||||
|
];
|
||||||
|
|
||||||
|
db.run(updateQuery, updateParams, function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error updating book in database:', err);
|
||||||
|
return res.status(500).json({ error: 'Failed to update book in database' });
|
||||||
|
} else {
|
||||||
|
res.json({ success: true, message: 'Book updated successfully' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Book does not exist, insert a new record
|
||||||
|
const insertQuery = `
|
||||||
|
INSERT INTO books (
|
||||||
|
isbn, title, authors, publishedDate, description, url,
|
||||||
|
number_of_pages, identifiers, publishers, subjects,
|
||||||
|
notes, cover_small, cover_medium, cover_large
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
`;
|
||||||
|
|
||||||
|
const insertParams = [
|
||||||
|
isbn, title, authors ? authors.join(', ') : '', publishedDate, description || '',
|
||||||
|
url, number_of_pages, identifiers, publishers, subjects,
|
||||||
|
notes, cover_small, cover_medium, cover_large
|
||||||
|
];
|
||||||
|
|
||||||
|
db.run(insertQuery, insertParams, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error('Error storing book in database:', err);
|
console.error('Error storing book in database:', err);
|
||||||
res.status(500).json({ error: 'Failed to store book in database' });
|
return res.status(500).json({ error: 'Failed to store book in database' });
|
||||||
} else {
|
} else {
|
||||||
res.json({ success: true, message: 'Book stored successfully', bookId: this.lastID });
|
res.json({ success: true, message: 'Book stored successfully', bookId: this.lastID });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function formatOpenLibraryData(data) {
|
function formatOpenLibraryData(data) {
|
||||||
return {
|
return {
|
||||||
isbn: data.identifiers.isbn_13 ? data.identifiers.isbn_13[0] : '',
|
isbn: data.identifiers.isbn_13 ? data.identifiers.isbn_13[0] : '',
|
||||||
@@ -96,16 +162,38 @@ function formatOpenLibraryData(data) {
|
|||||||
authors: data.authors ? data.authors.map(author => author.name) : [],
|
authors: data.authors ? data.authors.map(author => author.name) : [],
|
||||||
publishedDate: data.publish_date,
|
publishedDate: data.publish_date,
|
||||||
description: data.excerpts ? data.excerpts[0].text : 'No description available',
|
description: data.excerpts ? data.excerpts[0].text : 'No description available',
|
||||||
|
url: data.url,
|
||||||
|
number_of_pages: data.number_of_pages || null,
|
||||||
|
identifiers: JSON.stringify(data.identifiers), // Store as JSON string
|
||||||
|
publishers: data.publishers ? data.publishers.map(pub => pub.name).join(', ') : '',
|
||||||
|
subjects: data.subjects ? data.subjects.map(sub => sub.name).join(', ') : '',
|
||||||
|
notes: data.notes || '',
|
||||||
|
cover_small: data.cover ? data.cover.small : '',
|
||||||
|
cover_medium: data.cover ? data.cover.medium : '',
|
||||||
|
cover_large: data.cover ? data.cover.large : ''
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function formatArchiveData(data) {
|
function formatArchiveData(data) {
|
||||||
return {
|
return {
|
||||||
isbn: data.isbn ? data.isbn[0] : '',
|
isbn: data.isbn ? data.isbn[0] : '',
|
||||||
title: data.title,
|
title: data.title,
|
||||||
authors: data.creator,
|
authors: data.contributor ? [data.contributor] : [],
|
||||||
publishedDate: data.date,
|
publishedDate: data.date ? new Date(data.date).getFullYear() : '',
|
||||||
description: data.description ? data.description[0] : 'No description available',
|
description: data.description ? data.description.join(' ') : 'No description available',
|
||||||
|
url: `https://archive.org/details/${data.identifier}`,
|
||||||
|
number_of_pages: data.imagecount || null,
|
||||||
|
identifiers: JSON.stringify({
|
||||||
|
archive_identifier: data.identifier,
|
||||||
|
oclc: data['external-identifier'] ? data['external-identifier'].filter(id => id.includes('urn:oclc')).map(id => id.split(':')[2]) : []
|
||||||
|
}),
|
||||||
|
publishers: data.publisher || '',
|
||||||
|
subjects: data.subject ? data.subject.join(', ') : '',
|
||||||
|
notes: '', // Archive data does not provide specific notes like Open Library
|
||||||
|
cover_small: '', // Placeholder, as cover image URLs need to be constructed manually
|
||||||
|
cover_medium: '', // Same as above
|
||||||
|
cover_large: '' // Same as above
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,10 @@
|
|||||||
<div id="book-info"></div>
|
<div id="book-info"></div>
|
||||||
<div id="prompt">
|
<div id="prompt">
|
||||||
<p id="prompt-message"></p>
|
<p id="prompt-message"></p>
|
||||||
<button id="confirm">Yes</button>
|
<p id="book-title"></p>
|
||||||
|
<p id="book-author"></p>
|
||||||
|
<p id="book-desc"></p>
|
||||||
|
<button id="confirm">Add to Database</button>
|
||||||
<button id="edit-title">No, I'll add a title</button>
|
<button id="edit-title">No, I'll add a title</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="title-input">
|
<div id="title-input">
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ async function fetchBookInfo(isbn) {
|
|||||||
const bookData = await response.json();
|
const bookData = await response.json();
|
||||||
|
|
||||||
if (bookData.title) {
|
if (bookData.title) {
|
||||||
|
bookData.isbn2 = isbn; // Add the ISBN to the book data
|
||||||
promptUserWithBook(bookData);
|
promptUserWithBook(bookData);
|
||||||
} else {
|
} else {
|
||||||
console.log("No book data found. Restarting scanner...");
|
console.log("No book data found. Restarting scanner...");
|
||||||
@@ -101,12 +102,67 @@ async function fetchBookInfo(isbn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function promptUserWithBook(bookData) {
|
function promptUserWithBook(bookData) {
|
||||||
// Display book information or prompt the user for confirmation
|
// Prepare the information to display in the confirm dialog
|
||||||
document.getElementById('book-info').textContent = `Title: ${bookData.title}`;
|
const title = bookData.title;
|
||||||
document.getElementById('prompt').style.display = 'block';
|
const authors = bookData.authors ? bookData.authors.join(', ') : 'Unknown Author';
|
||||||
// Additional logic for user confirmation can be added here
|
const description = bookData.description || 'No description available';
|
||||||
|
|
||||||
|
// Combine the information into a single message
|
||||||
|
const message = `Title: ${title}\nAuthor(s): ${authors}\nDescription: ${description}\n\nDo you want to add this book to the database?`;
|
||||||
|
|
||||||
|
// Use the built-in confirm prompt to ask the user
|
||||||
|
const userConfirmed = confirm(message);
|
||||||
|
|
||||||
|
if (userConfirmed) {
|
||||||
|
console.log('User confirmed to add the book to the database.');
|
||||||
|
storeBookInDatabase(bookData);
|
||||||
|
} else {
|
||||||
|
console.log('User declined to add the book to the database.');
|
||||||
|
startScanner(); // Restart the scanner if the user declines
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function storeBookInDatabase(bookData) {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/store-book', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
isbn: bookData.isbn || bookData.isbn2,
|
||||||
|
title: bookData.title,
|
||||||
|
authors: bookData.authors,
|
||||||
|
publishedDate: bookData.publishedDate,
|
||||||
|
description: bookData.description,
|
||||||
|
url: bookData.url,
|
||||||
|
number_of_pages: bookData.number_of_pages,
|
||||||
|
identifiers: bookData.identifiers,
|
||||||
|
publishers: bookData.publishers,
|
||||||
|
subjects: bookData.subjects,
|
||||||
|
notes: bookData.notes,
|
||||||
|
cover_small: bookData.cover_small,
|
||||||
|
cover_medium: bookData.cover_medium,
|
||||||
|
cover_large: bookData.cover_large
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
alert('Book added to the database successfully!');
|
||||||
|
} else {
|
||||||
|
alert('Failed to add the book to the database.');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error storing book in database:', error);
|
||||||
|
alert('An error occurred while storing the book.');
|
||||||
|
} finally {
|
||||||
|
startScanner(); // Restart the scanner after storing the book or handling errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Start the scanner when the start button is clicked
|
// Start the scanner when the start button is clicked
|
||||||
document.getElementById('start-scanner').addEventListener('click', startScanner);
|
document.getElementById('start-scanner').addEventListener('click', startScanner);
|
||||||
|
|
||||||
|
|||||||
@@ -23,3 +23,12 @@ canvas.drawing, canvas.drawingBuffer {
|
|||||||
#title-input {
|
#title-input {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#prompt-message {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#book-title, #book-author, #book-desc {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user