forked from paul-hanneforth/instagram-bot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tools.js
130 lines (116 loc) · 4.57 KB
/
tools.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
const util = require("./util.js");
const newPage = async (browser, url) => {
// create page
const page = await browser.newPage();
// change language
await page.setExtraHTTPHeaders({
'Accept-Language': 'en'
});
// set url
await page.goto(url);
return page;
}
const evaluate = async (page, js, args) => {
const result = await page.evaluate(js, args);
return result;
}
const clickOn = async (page, querySelector, property) => {
await evaluate(page, (args) => {
const elements = [...document.querySelectorAll(args.querySelector)];
const keysProp = Object.keys((args.property ? args.property : {}));
elements.forEach((element) => {
const matchesProperties = keysProp.reduce((acc, cur) => {
if (args.property[cur] == element[cur]) return true;
return false;
}, true)
if (matchesProperties) element.click();
})
}, { querySelector, property })
}
const clickOnOne = async (page, querySelector, property) => {
const clickedElement = await evaluate(page, (args) => {
const elements = [...document.querySelectorAll(args.querySelector)];
const keysProp = Object.keys((args.property ? args.property : {}));
const clickedElement = elements.reduce((alreadyClicked, element) => {
if(alreadyClicked) return true;
const matchesProperties = keysProp.reduce((acc, cur) => {
if (args.property[cur] == element[cur]) return true;
return false;
}, true)
if (matchesProperties) {
element.click();
return true;
}
return alreadyClicked;
}, false)
return clickedElement;
}, { querySelector, property })
return clickedElement;
}
const clickOnButton = async (page, buttonText) => {
await clickOn(page, "button", { innerText: buttonText });
}
const clickOnDiv = async (page, text) => {
await evaluate(page, (innerText) => {
const matchingDivs = [...document.querySelectorAll("div")];
matchingDivs.forEach((div) => {
if (div.innerText === innerText) div.click();
})
}, text);
}
const scrollBy = async (page, scroll, boxSelector) => {
await evaluate(page, async ({ boxSelector, scroll }) => {
const box = boxSelector ? document.querySelector(boxSelector) : document.scrollingElement;
box?.scrollBy(0, scroll);
}, { boxSelector, scroll })
}
const scroll = async (page, boxSelector) => {
await evaluate(page, async (boxSelector) => {
const box = boxSelector ? document.querySelector(boxSelector) : document.scrollingElement;
const scroll = async (box, scrollTop) => {
box?.scrollBy(0, 1000);
// wait for 1 second
await new Promise((resolve) => setTimeout(resolve, 1 * 1000));
if (scrollTop != box.scrollTop) await scroll(box, box.scrollTop);
}
await scroll(box, box.scrollTop);
}, boxSelector)
}
const loadElementsFromList = async (page, boxSelector, fetchFunction, compareFunction, minElements) => {
const load = async (minElements, oldElementList = [], oldScrollTop) => {
// wait
await util.wait(1000 * 2);
// scroll down
await scrollBy(page, 500, boxSelector);
// get loaded elements
const loadedElements = await page.evaluate(fetchFunction);
// concat oldElementList with new elementList
const elementList = oldElementList.concat(loadedElements);
// filter out duplicate elements
const filteredElementList = elementList.reduce((prev, element) => {
if(compareFunction(prev, element)) return prev;
return prev.concat([element]);
}, []);
// check if end of follower list has been reached
const scrollTop = await page.evaluate((boxSelector) => (boxSelector ? document.querySelector(boxSelector) : document.scrollingElement).scrollTop, boxSelector);
if(scrollTop == oldScrollTop) return filteredElementList;
// check if enough elements have been loaded
if(minElements <= filteredElementList.length) return filteredElementList;
// recursively rerun function until enough elements have been loaded
const result = await load(minElements, filteredElementList, scrollTop);
return result;
}
const result = await load(minElements);
return result;
}
module.exports = {
newPage,
evaluate,
clickOn,
clickOnOne,
clickOnButton,
clickOnDiv,
scroll,
scrollBy,
loadElementsFromList
}