diff --git a/package.json b/package.json index 4c8462a..71814b8 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "chokidar": "^4.0.3", "cross-env": "^7.0.3", "crx": "^5.0.1", + "emittery": "^1.1.0", "esno": "^4.8.0", "fs-extra": "^11.2.0", "husky": "^9.1.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d9723c..ac906bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ importers: crx: specifier: ^5.0.1 version: 5.0.1 + emittery: + specifier: ^1.1.0 + version: 1.1.0 esno: specifier: ^4.8.0 version: 4.8.0 @@ -1381,6 +1384,10 @@ packages: engines: {node: '>=14'} hasBin: true + emittery@1.1.0: + resolution: {integrity: sha512-rsX7ktqARv/6UQDgMaLfIqUWAEzzbCQiVh7V9rhDXp6c37yoJcks12NVD+XPkgl4AEavmNhVfrhGoqYwIsMYYA==} + engines: {node: '>=14.16'} + emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} @@ -4869,6 +4876,8 @@ snapshots: minimatch: 9.0.1 semver: 7.6.3 + emittery@1.1.0: {} + emoji-regex@10.4.0: {} emoji-regex@8.0.0: {} diff --git a/src/logic/page-worker/index.ts b/src/logic/page-worker/index.ts index b4a4c63..d72172b 100644 --- a/src/logic/page-worker/index.ts +++ b/src/logic/page-worker/index.ts @@ -1,4 +1,9 @@ +import Emittery from 'emittery'; +import { AmazonPageWorker, AmazonPageWorkerEvents } from './types'; + class AmazonPageWorkerImpl implements AmazonPageWorker { + readonly channel = new Emittery(); + public async doSearch(keywords: string): Promise { const url = new URL('https://www.amazon.com/s'); url.searchParams.append('k', keywords); @@ -16,7 +21,7 @@ class AmazonPageWorkerImpl implements AmazonPageWorker { return url.toString(); } - public async wanderSearchList(): Promise { + private async wanderSearchSinglePage() { const tab = await browser.tabs .query({ active: true, currentWindow: true }) .then((tabs) => tabs[0]); @@ -31,6 +36,15 @@ class AmazonPageWorkerImpl implements AmazonPageWorker { window.scrollBy(0, ~~(Math.random() * 500) + 500); await new Promise((resolve) => setTimeout(resolve, 10)); } + const items = document.querySelectorAll( + '.a-section.a-spacing-small.puis-padding-left-small', + ); + const links: string[] = []; + items.forEach((el) => { + const link = + el.querySelector('a.a-link-normal')?.href; + link && links.push(link); + }); const nextButton = document.querySelector('.s-pagination-next'); if ( @@ -41,14 +55,25 @@ class AmazonPageWorkerImpl implements AmazonPageWorker { setTimeout(resolve, 500 + ~~(500 * Math.random())), ); nextButton.click(); + } else { + return null; } - return true; + return links; } catch (e) { - return false; + return null; } }, }); - console.log('results', results); + await new Promise((resolve) => setTimeout(resolve, 1000)); + return results.pop()?.result as string[] | null; + } + + public async wanderSearchList(): Promise { + let links = await this.wanderSearchSinglePage(); + while (links) { + this.channel.emit('item-links-collected', { links }); + links = await this.wanderSearchSinglePage(); + } return new Promise((resolve) => setTimeout(resolve, 1000)); } } diff --git a/src/logic/page-worker/types.d.ts b/src/logic/page-worker/types.d.ts index 4741766..a51f085 100644 --- a/src/logic/page-worker/types.d.ts +++ b/src/logic/page-worker/types.d.ts @@ -1,4 +1,21 @@ +import type Emittery from 'emittery'; + +interface AmazonPageWorkerEvents { + /** + * Emitted when a new item is found on the Amazon page. + * @param link - The item link that was found. + */ + ['item-links-collected']: { links: string[] }; +} + + interface AmazonPageWorker { + /** + * The channel for communication with the Amazon page worker. + * This is an instance of Emittery, which allows for event-based communication. + */ + readonly channel: Emittery; + /** * Search for a list of items on Amazon * @param keywords - The keywords to search for on Amazon. diff --git a/src/sidepanel/Sidepanel.vue b/src/sidepanel/Sidepanel.vue index 0bcddab..e1dcb38 100644 --- a/src/sidepanel/Sidepanel.vue +++ b/src/sidepanel/Sidepanel.vue @@ -2,11 +2,19 @@ import { keywords } from '~/logic/storage'; import pageWorker from '~/logic/page-worker'; +const links = ref([]); +const worker = pageWorker.createAmazonPageWorker(); + +onMounted(() => { + worker.channel.on('item-links-collected', (ev) => { + links.value = links.value.concat(ev.links); + }); +}); + const onSearch = async () => { if (keywords.value.trim() === '') { return; } - const worker = pageWorker.createAmazonPageWorker(); await worker.doSearch(keywords.value); await worker.wanderSearchList(); }; @@ -31,13 +39,18 @@ const onSearch = async () => {
- + + + + {{ link }} + +