import { Book } from "../lib/book" import { storageGet } from "../lib/storage" import { client } from "./client" import { setLastSyncAt } from "./sync-status" export const KINDLE_OWNED_CONTENT_REQUEST = 'kindle-owned-content-request' export const startKindleAuth = () => { return window.open('https://read.amazon.com') } export const performSync = async () => { console.log('Starting Kindle sync...') setLastSyncAt() const content = await fetchOwnedContent() if (!content) return const books = await convertOwnedContentToBooks(content) console.log('Got books: ', books) client.syncBooks(books) } const convertOwnedContentToBooks = async (content):Promise => { const books:Book[] = [] for (const asin in content.asinsToAdd) { const asinItem = content.asinsToAdd[asin] const notes = await fetchNotes(asinItem.asin) books.push({ asin: asinItem.asin, authors: asinItem.authors, publication_date: asinItem.publicationDate, purchase_date: asinItem.purchaseDate, title: asinItem.title, notes, }) } return books } const getLastOwnedContentRequest = () => { return storageGet( KINDLE_OWNED_CONTENT_REQUEST ) as any } const fetchOwnedContent = async () => { const request = await getLastOwnedContentRequest() if ( !request ) { console.error('No stored requests') return } const url = new URL(request.url) url.search = '' const response = await fetch( url.href, {headers: request.headers} ) if ( response.status !== 200 ) { console.error('Invalid response', response) return } return response.json() } const fetchNotes = async (asin: string) => { console.log(`Fetching notes for ${asin}...`) const url = new URL('https://read.amazon.com/notebook') url.searchParams.append('asin', asin) url.searchParams.append('contentLimitState', '') const response = await fetch(url.href, { credentials: 'include' }) return parseNotesFragment(await response.text()) } const parseNotesFragment = (htmlString: string) => { const parser = new DOMParser() const doc = parser.parseFromString(htmlString , 'text/html') const notes = [] for (const node of doc.querySelectorAll('.a-row.a-spacing-base')) { const pageText = node.querySelector('.kp-notebook-metadata')?.textContent const highlightText = node.querySelector('.kp-notebook-highlight')?.textContent const noteText = node.querySelector('.kp-notebook-note')?.textContent const [,extractedPage] = pageText?.match(/Page:\s+(\d+)/) || [] const page = extractedPage ? parseInt(extractedPage, 10) : -1 const highlight = highlightText?.replace(/^Highlight:/, '')?.trim() const note = noteText?.replace(/^Note:/, '')?.trim() if (page > -1 && (highlightText || noteText)) { notes.push({ page, type: highlight ? 'highlight' : 'note', value: highlight || note }) } } return notes }