Extractor.watch() improvements
- only watch current window - stop watch on window close - don't ask user to confirm when fails
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
import { Actions, Request } from "../common";
|
import { Actions, Request } from "../common";
|
||||||
import { sendMessage } from "./messaging";
|
import { sendMessage } from "./messaging";
|
||||||
|
import { logger } from "./common";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* redirect tab to url.
|
* redirect tab to url.
|
||||||
@ -41,7 +42,7 @@ export function redirectTab(tab: chrome.tabs.Tab, url: string) {
|
|||||||
* @param {Array<string>} fieldSelectors fields selectors for selecting fields (data columns) under each item
|
* @param {Array<string>} fieldSelectors fields selectors for selecting fields (data columns) under each item
|
||||||
* @returns {Promise<string[]>} a promise of extracted data
|
* @returns {Promise<string[]>} a promise of extracted data
|
||||||
*/
|
*/
|
||||||
export function extractTabData(tab, itemsSelector, fieldSelectors) {
|
export function extractTabData(tab: chrome.tabs.Tab, itemsSelector: string, fieldSelectors: string[], askOnfail?: boolean) {
|
||||||
let req = {
|
let req = {
|
||||||
action: Actions.EXTRACT,
|
action: Actions.EXTRACT,
|
||||||
itemsSelector: itemsSelector,
|
itemsSelector: itemsSelector,
|
||||||
@ -49,7 +50,13 @@ export function extractTabData(tab, itemsSelector, fieldSelectors) {
|
|||||||
}
|
}
|
||||||
let checker = (result, err, tryCount) => {
|
let checker = (result, err, tryCount) => {
|
||||||
if (!result || !result.length) {
|
if (!result || !result.length) {
|
||||||
if (tryCount % 20 == 0 && confirm('No data found in current page. \n\nContinue to next page?')) {
|
if (
|
||||||
|
tryCount % 20 == 0 && (
|
||||||
|
!askOnfail ||
|
||||||
|
confirm('No data found in current page. \n\nContinue to next page?')
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
logger.warn(`Failed after ${tryCount} tries: ${tab.url}`)
|
||||||
return [];
|
return [];
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -135,6 +142,25 @@ export async function findIncognitoWindow(): Promise<chrome.windows.Window> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getCurrentWindow(): Promise<chrome.windows.Window> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.windows.getCurrent(
|
||||||
|
(windows: chrome.windows.Window) => {
|
||||||
|
return resolve(windows);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getWindowByID(id: number) {
|
||||||
|
return new Promise<chrome.windows.Window>((resolve, reject) => {
|
||||||
|
chrome.windows.get(id, function (window) {
|
||||||
|
chrome.runtime.lastError;
|
||||||
|
resolve(window);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export async function CreateIncognitoWindow() {
|
export async function CreateIncognitoWindow() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
chrome.windows.create(
|
chrome.windows.create(
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export function sendMessage<T>(
|
|||||||
loop();
|
loop();
|
||||||
|
|
||||||
async function loop() {
|
async function loop() {
|
||||||
logger.debug("Request for", req.action);
|
logger.debug("Request for", Actions[req.action]);
|
||||||
let tabAvailable = await getTabByID(tab.id);
|
let tabAvailable = await getTabByID(tab.id);
|
||||||
if (!tabAvailable) {
|
if (!tabAvailable) {
|
||||||
reject("Task interrupted due to the target tab is closed.");
|
reject("Task interrupted due to the target tab is closed.");
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { parseUrls } from "./tools";
|
import { parseUrls } from "./tools";
|
||||||
import { queryUrl, redirectTab, scrollToBottom, extractTabData } from "./actions";
|
import { queryUrl, redirectTab, scrollToBottom, extractTabData, findIncognitoWindow, getCurrentWindow, getWindowByID } from "./actions";
|
||||||
import { testArgs, signitures } from "./signiture";
|
import { testArgs, signitures } from "./signiture";
|
||||||
import { ExtractResult } from "./result";
|
import { ExtractResult } from "./result";
|
||||||
import { messageSubscribers, ActionSubscriber } from "./messaging";
|
import { messageSubscribers, ActionSubscriber } from "./messaging";
|
||||||
@ -14,6 +14,7 @@ export class Task {
|
|||||||
private _fieldSelectors: string[];
|
private _fieldSelectors: string[];
|
||||||
private _urls: string[] = [];
|
private _urls: string[] = [];
|
||||||
private _running = false;
|
private _running = false;
|
||||||
|
private _listeners: ActionSubscriber[] = [];
|
||||||
|
|
||||||
constructor(options: any, ...arg: any);
|
constructor(options: any, ...arg: any);
|
||||||
constructor(options: any, itemsSelector: string, fieldSelectors: string[]);
|
constructor(options: any, itemsSelector: string, fieldSelectors: string[]);
|
||||||
@ -56,15 +57,46 @@ export class Task {
|
|||||||
}
|
}
|
||||||
stop() {
|
stop() {
|
||||||
this._running = false;
|
this._running = false;
|
||||||
messageSubscribers.removeListener(Actions.REPORT_NEW_PAGE, this.listener);
|
let listener: ActionSubscriber;
|
||||||
|
while (listener = this._listeners.pop()) {
|
||||||
|
messageSubscribers.removeListener(Actions.REPORT_NEW_PAGE, listener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
watch() {
|
async watch() {
|
||||||
if (this._running) {
|
if (this._running) {
|
||||||
logger.info("The task is running. Please wait...");
|
logger.info("The task is running. Please wait...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._running = true;
|
this._running = true;
|
||||||
messageSubscribers.addListener(Actions.REPORT_NEW_PAGE, this.listener);
|
let window = await findIncognitoWindow() || await getCurrentWindow();
|
||||||
|
if (!window) {
|
||||||
|
logger.info("No window to watch...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let listener: ActionSubscriber = async (request, sender, sendResponse) => {
|
||||||
|
let findWindow = await getWindowByID(window.id);
|
||||||
|
if (!findWindow) {
|
||||||
|
// stop watch on window close.
|
||||||
|
messageSubscribers.removeListener(Actions.REPORT_NEW_PAGE, listener);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// only watch current window.
|
||||||
|
if (sender.tab.windowId != window.id) return;
|
||||||
|
let pm = this.makeOptionalTasks(sender.tab);
|
||||||
|
return pm.then(
|
||||||
|
() => extractTabData(sender.tab, this._itemsSelector, this._fieldSelectors, false)
|
||||||
|
).then(
|
||||||
|
results => {
|
||||||
|
if (results && results.length) {
|
||||||
|
this.saveResult(results, sender.tab.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).catch(
|
||||||
|
e => logger.error(e)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
this._listeners.push(listener);
|
||||||
|
messageSubscribers.addListener(Actions.REPORT_NEW_PAGE, listener);
|
||||||
}
|
}
|
||||||
async execute(tab: chrome.tabs.Tab, upstreamData?: ExtractResult): Promise<void> {
|
async execute(tab: chrome.tabs.Tab, upstreamData?: ExtractResult): Promise<void> {
|
||||||
if (!tab) return Promise.reject("No tab to execute the task.");
|
if (!tab) return Promise.reject("No tab to execute the task.");
|
||||||
@ -108,21 +140,6 @@ export class Task {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
private listener: ActionSubscriber = (request, sender, sendResponse) => {
|
|
||||||
sendResponse('recieved!');
|
|
||||||
let pm = this.makeOptionalTasks(sender.tab);
|
|
||||||
return pm.then(
|
|
||||||
() => extractTabData(sender.tab, this._itemsSelector, this._fieldSelectors)
|
|
||||||
).then(
|
|
||||||
results => {
|
|
||||||
if (results && results.length) {
|
|
||||||
this.saveResult(results, sender.tab.url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
).catch(
|
|
||||||
e => logger.error(e)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
private makeOptionalTasks(tab: chrome.tabs.Tab): Promise<any> {
|
private makeOptionalTasks(tab: chrome.tabs.Tab): Promise<any> {
|
||||||
let pm: Promise<any>;
|
let pm: Promise<any>;
|
||||||
if (this._options["scrollToBottom"]) {
|
if (this._options["scrollToBottom"]) {
|
||||||
|
|||||||
Reference in New Issue
Block a user