instauto 7.2.2 → 7.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +66 -36
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -165,27 +165,45 @@ const Instauto = async (db, browser, options) => {
|
|
|
165
165
|
return new Date().getTime() - followedUserEntry.time < dontUnfollowUntilTimeElapsed;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
async function
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
168
|
+
async function gotoWithRetry(url) {
|
|
169
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
170
|
+
logger.log(`Goto ${url}`);
|
|
171
|
+
const response = await page.goto(url);
|
|
172
|
+
await sleep(1000);
|
|
173
|
+
const status = response.status();
|
|
174
|
+
|
|
175
|
+
// https://www.reddit.com/r/Instagram/comments/kwrt0s/error_560/
|
|
176
|
+
// https://github.com/mifi/instauto/issues/60
|
|
177
|
+
if (![560, 429].includes(status) || attempt > 3) return status;
|
|
178
|
+
|
|
179
|
+
logger.info(`Got ${status} - Retrying request later...`);
|
|
180
|
+
if (status === 429) logger.warn('429 Too Many Requests could mean that Instagram suspects you\'re using a bot. You could try to use the Instagram Mobile app from the same IP for a few days first');
|
|
181
|
+
await sleep((attempt + 1) * 30 * 60 * 1000);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function safeGotoUser(url, checkPageForUsername) {
|
|
186
|
+
const status = await gotoWithRetry(url);
|
|
173
187
|
if (status === 200) {
|
|
188
|
+
if (checkPageForUsername != null) {
|
|
189
|
+
// some pages return 200 but nothing there (I think deleted accounts)
|
|
190
|
+
// https://github.com/mifi/SimpleInstaBot/issues/48
|
|
191
|
+
// example: https://www.instagram.com/victorialarson__/
|
|
192
|
+
// so we check if the page has the user's name on it
|
|
193
|
+
return page.evaluate((username) => window.find(username), checkPageForUsername);
|
|
194
|
+
}
|
|
174
195
|
return true;
|
|
175
|
-
}
|
|
196
|
+
}
|
|
197
|
+
if (status === 404) {
|
|
176
198
|
logger.log('User not found');
|
|
177
199
|
return false;
|
|
178
|
-
} else if (status === 429) {
|
|
179
|
-
logger.error('Got 429 Too Many Requests, waiting...');
|
|
180
|
-
await sleep(60 * 60 * 1000);
|
|
181
|
-
throw new Error('Aborted operation due to too many requests'); // TODO retry instead
|
|
182
200
|
}
|
|
183
|
-
throw new Error(`Navigate to user
|
|
201
|
+
throw new Error(`Navigate to user failed with status ${status}`);
|
|
184
202
|
}
|
|
185
203
|
|
|
186
204
|
async function navigateToUser(username) {
|
|
187
205
|
logger.log(`Navigating to user ${username}`);
|
|
188
|
-
return
|
|
206
|
+
return safeGotoUser(`${instagramBaseUrl}/${encodeURIComponent(username)}`, username);
|
|
189
207
|
}
|
|
190
208
|
|
|
191
209
|
async function getPageJson() {
|
|
@@ -197,7 +215,7 @@ const Instauto = async (db, browser, options) => {
|
|
|
197
215
|
if (graphqlUserMissing) {
|
|
198
216
|
// https://stackoverflow.com/questions/37593025/instagram-api-get-the-userid
|
|
199
217
|
// https://stackoverflow.com/questions/17373886/how-can-i-get-a-users-media-from-instagram-without-authenticating-as-a-user
|
|
200
|
-
const found = await
|
|
218
|
+
const found = await safeGotoUser(`${instagramBaseUrl}/${encodeURIComponent(username)}?__a=1`);
|
|
201
219
|
if (!found) throw new Error('User not found');
|
|
202
220
|
|
|
203
221
|
const json = await getPageJson();
|
|
@@ -320,7 +338,7 @@ const Instauto = async (db, browser, options) => {
|
|
|
320
338
|
await addPrevFollowedUser(entry);
|
|
321
339
|
|
|
322
340
|
if (!elementHandle2) {
|
|
323
|
-
logger.log('Button did not change state - Sleeping');
|
|
341
|
+
logger.log('Button did not change state - Sleeping 1 min');
|
|
324
342
|
await sleep(60000);
|
|
325
343
|
throw new Error('Button did not change state');
|
|
326
344
|
}
|
|
@@ -791,6 +809,10 @@ const Instauto = async (db, browser, options) => {
|
|
|
791
809
|
}
|
|
792
810
|
|
|
793
811
|
page = await browser.newPage();
|
|
812
|
+
|
|
813
|
+
// https://github.com/mifi/SimpleInstaBot/issues/118#issuecomment-1067883091
|
|
814
|
+
await page.setExtraHTTPHeaders({ 'Accept-Language': 'en' });
|
|
815
|
+
|
|
794
816
|
if (randomizeUserAgent) {
|
|
795
817
|
const userAgentGenerated = new UserAgent({ deviceCategory: 'desktop' });
|
|
796
818
|
await page.setUserAgent(userAgentGenerated.toString());
|
|
@@ -802,27 +824,19 @@ const Instauto = async (db, browser, options) => {
|
|
|
802
824
|
const goHome = async () => page.goto(`${instagramBaseUrl}/?hl=en`);
|
|
803
825
|
|
|
804
826
|
// https://github.com/mifi/SimpleInstaBot/issues/28
|
|
805
|
-
async function setLang(short, long) {
|
|
827
|
+
async function setLang(short, long, assumeLoggedIn = false) {
|
|
806
828
|
logger.log(`Setting language to ${long} (${short})`);
|
|
807
829
|
|
|
808
|
-
// This doesn't seem to always work, hence why it's just a fallback now
|
|
809
|
-
async function fallbackSetLang() {
|
|
810
|
-
await goHome();
|
|
811
|
-
await sleep(1000);
|
|
812
|
-
|
|
813
|
-
await page.setCookie({
|
|
814
|
-
name: 'ig_lang',
|
|
815
|
-
value: short,
|
|
816
|
-
path: '/',
|
|
817
|
-
});
|
|
818
|
-
await sleep(1000);
|
|
819
|
-
await goHome();
|
|
820
|
-
await sleep(3000);
|
|
821
|
-
}
|
|
822
|
-
|
|
823
830
|
try {
|
|
824
831
|
await sleep(1000);
|
|
825
|
-
|
|
832
|
+
|
|
833
|
+
// when logged in, we need to go to account in order to be able to check/set language
|
|
834
|
+
// (need to see the footer)
|
|
835
|
+
if (assumeLoggedIn) {
|
|
836
|
+
await page.goto(`${instagramBaseUrl}/accounts/edit/`);
|
|
837
|
+
} else {
|
|
838
|
+
await goHome();
|
|
839
|
+
}
|
|
826
840
|
await sleep(3000);
|
|
827
841
|
const elementHandles = await page.$x(`//select[//option[@value='${short}' and text()='${long}']]`);
|
|
828
842
|
if (elementHandles.length < 1) throw new Error('Language selector not found');
|
|
@@ -841,6 +855,10 @@ const Instauto = async (db, browser, options) => {
|
|
|
841
855
|
|
|
842
856
|
if (alreadyEnglish) {
|
|
843
857
|
logger.log('Already English language');
|
|
858
|
+
if (!assumeLoggedIn) {
|
|
859
|
+
await goHome(); // because we were on the settings page
|
|
860
|
+
await sleep(1000);
|
|
861
|
+
}
|
|
844
862
|
return;
|
|
845
863
|
}
|
|
846
864
|
|
|
@@ -850,12 +868,23 @@ const Instauto = async (db, browser, options) => {
|
|
|
850
868
|
await sleep(1000);
|
|
851
869
|
} catch (err) {
|
|
852
870
|
logger.error('Failed to set language, trying fallback (cookie)', err);
|
|
853
|
-
|
|
871
|
+
// This doesn't seem to always work, hence why it's just a fallback now
|
|
872
|
+
await goHome();
|
|
873
|
+
await sleep(1000);
|
|
874
|
+
|
|
875
|
+
await page.setCookie({
|
|
876
|
+
name: 'ig_lang',
|
|
877
|
+
value: short,
|
|
878
|
+
path: '/',
|
|
879
|
+
});
|
|
880
|
+
await sleep(1000);
|
|
881
|
+
await goHome();
|
|
882
|
+
await sleep(3000);
|
|
854
883
|
}
|
|
855
884
|
}
|
|
856
885
|
|
|
857
|
-
const setEnglishLang = async () => setLang('en', 'English');
|
|
858
|
-
// const setEnglishLang = async () => setLang('de', 'Deutsch');
|
|
886
|
+
const setEnglishLang = async (assumeLoggedIn) => setLang('en', 'English', assumeLoggedIn);
|
|
887
|
+
// const setEnglishLang = async (assumeLoggedIn) => setLang('de', 'Deutsch', assumeLoggedIn);
|
|
859
888
|
|
|
860
889
|
async function tryPressButton(elementHandles, name, sleepMs = 3000) {
|
|
861
890
|
try {
|
|
@@ -869,7 +898,7 @@ const Instauto = async (db, browser, options) => {
|
|
|
869
898
|
}
|
|
870
899
|
}
|
|
871
900
|
|
|
872
|
-
await setEnglishLang();
|
|
901
|
+
await setEnglishLang(false);
|
|
873
902
|
|
|
874
903
|
await tryPressButton(await page.$x('//button[contains(text(), "Accept")]'), 'Accept cookies dialog');
|
|
875
904
|
await tryPressButton(await page.$x('//button[contains(text(), "Only allow essential cookies")]'), 'Accept cookies dialog 2 button 1', 10000);
|
|
@@ -924,7 +953,8 @@ const Instauto = async (db, browser, options) => {
|
|
|
924
953
|
}
|
|
925
954
|
|
|
926
955
|
// In case language gets reset after logging in
|
|
927
|
-
|
|
956
|
+
// https://github.com/mifi/SimpleInstaBot/issues/118
|
|
957
|
+
await setEnglishLang(true);
|
|
928
958
|
|
|
929
959
|
// Mobile version https://github.com/mifi/SimpleInstaBot/issues/7
|
|
930
960
|
await tryPressButton(await page.$x('//button[contains(text(), "Save Info")]'), 'Login info dialog: Save Info');
|