Skip to content

Commit

Permalink
add autoclick behavior!
Browse files Browse the repository at this point in the history
  • Loading branch information
ikreymer committed Nov 30, 2024
1 parent 6e9c90b commit ad8a8b2
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 3 deletions.
2 changes: 1 addition & 1 deletion dist/behaviors.js

Large diffs are not rendered by default.

125 changes: 125 additions & 0 deletions src/autoclick.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { BackgroundBehavior } from "./lib/behavior";
import { sleep } from "./lib/utils";

export class AutoClick extends BackgroundBehavior
{
_donePromise: Promise<void>;
_markDone: () => void;
selector: string;
seen = new Set<string>();

constructor(selector = "a[href]") {
super();
this.selector = selector;
this._donePromise = new Promise<void>((resolve) => this._markDone = resolve);
}

beforeUnload(event) {
event.preventDefault();
return false;
}

nextExternalElem(origNoHash: string) : HTMLAnchorElement | null {
try {
const allLinks = document.querySelectorAll(this.selector);
for (const el of allLinks) {
const elem = el as HTMLAnchorElement;
if (!elem.href || elem.href.startsWith(origNoHash)) {
continue;
}
if (!this.seen.has(elem.href)) {
return elem;
}
}
} catch (e) {
this.debug(e.toString());
}

return null;
}

async start() {
const origHref = self.location.href;

const url = new URL(origHref);
url.hash = "";
const origNoHash = url.href + "#";

// process all links (except hash links) which could result in attempted navigation
window.addEventListener("beforeunload", (e) => this.beforeUnload(e));

// eslint-disable-next-line no-constant-condition
while (true) {
const elem = this.nextExternalElem(origNoHash);

if (!elem) {
break;
}

await this.processElem(elem, origHref);
}

// process hashlinks on same page
for (const el of document.querySelectorAll(this.selector)) {
const elem = el as HTMLAnchorElement;
if (elem.href.startsWith(origNoHash)) {
await this.processElem(elem, origHref);
}
}

window.removeEventListener("beforeunload", (e) => this.beforeUnload(e));

this._markDone();
}

async processElem(elem: HTMLAnchorElement, origHref: string) {
const href = elem.href;

this.seen.add(href);

if (!elem.isConnected) {
return;
}

if (!href.startsWith(self.location.origin)) {
//this.log("external origin: " + elem.href);
return;
}

const anySelf = self as any;

if (anySelf.getEventListeners && !anySelf.getEventListeners(elem).click) {
//this.log("no click: " + href);
return;
}

if (anySelf.__bx_addSet && !await anySelf.__bx_addSet(href)) {
//this.log("already clicked: " + elem.href);
return;
}

this.debug("Clicking on " + href);

elem.click();

await sleep(500);

if (self.location.href != origHref) {
await new Promise((resolve) => {
window.addEventListener("popstate", () => {
resolve(null);
}, { once: true });

window.history.back();
});

await sleep(500);
}
} catch (e) {
this.debug(e.toString());
}

done() {
return this._donePromise;
}
}
12 changes: 11 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AutoFetcher } from "./autofetcher";
import { Autoplay } from "./autoplay";
import { AutoScroll } from "./autoscroll";
import { AutoClick } from "./autoclick";
import { awaitLoad, sleep, behaviorLog, _setLogFunc, _setBehaviorManager, installBehaviors } from "./lib/utils";
import { Behavior, BehaviorRunner } from "./lib/behavior";

Expand All @@ -15,14 +16,18 @@ interface BehaviorManagerOpts {
autofetch?: boolean;
autoplay?: boolean;
autoscroll?: boolean;
autoclick?: boolean;
log?: ((...message: string[]) => void) | string | false;
siteSpecific?: boolean | object;
timeout?: number;
fetchHeaders?: object | null;
startEarly?: boolean | null;
clickSelector?: string;
}

const DEFAULT_OPTS: BehaviorManagerOpts = {autofetch: true, autoplay: true, autoscroll: true, siteSpecific: true};
const DEFAULT_OPTS: BehaviorManagerOpts = {autofetch: true, autoplay: true, autoscroll: true, autoclick: true, siteSpecific: true};

const DEFAULT_SELECTOR = "a[href]";

export class BehaviorManager {
autofetch: AutoFetcher;
Expand Down Expand Up @@ -89,6 +94,11 @@ export class BehaviorManager {
this.behaviors.push(new Autoplay(this.autofetch, opts.startEarly));
}

if (opts.autoclick) {
behaviorLog("Using AutoClick");
this.behaviors.push(new AutoClick(opts.clickSelector || DEFAULT_SELECTOR));
}

if (!this.isInTopFrame()) {
return;
}
Expand Down
3 changes: 2 additions & 1 deletion src/site/facebook.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const Q = {
feed: "//div[@role='feed']",
//feed: "//div[@role='feed']",
feed: "//div[@role='main']/div[4]/div[2]/div/div[2]/div[2]",
article: ".//div[@role='article']",
pageletPostList: "//div[@data-pagelet='page']/div[@role='main']//div[@role='main']/div",
pageletProfilePostList: "//div[@data-pagelet='page']//div[@data-pagelet='ProfileTimeline']",
Expand Down

0 comments on commit ad8a8b2

Please sign in to comment.