instauto 9.1.11 → 9.2.1

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.
Files changed (2) hide show
  1. package/package.json +1 -2
  2. package/src/index.js +55 -19
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instauto",
3
- "version": "9.1.11",
3
+ "version": "9.2.1",
4
4
  "description": "Instagram automation library written in Node.js",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -23,7 +23,6 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "eslint": "^7.32.0 || ^8.2.0",
26
- "eslint-config-airbnb": "^16.1.0",
27
26
  "eslint-config-airbnb-base": "^15.0.0",
28
27
  "eslint-plugin-import": "^2.25.2",
29
28
  "puppeteer": "^1.19.0"
package/src/index.js CHANGED
@@ -55,6 +55,7 @@ const Instauto = async (db, browser, options) => {
55
55
  followUserMinFollowing = null,
56
56
 
57
57
  shouldFollowUser = null,
58
+ shouldLikeMedia = null,
58
59
 
59
60
  dontUnfollowUntilTimeElapsed = 3 * 24 * 60 * 60 * 1000,
60
61
 
@@ -128,11 +129,13 @@ const Instauto = async (db, browser, options) => {
128
129
  }
129
130
  }
130
131
 
132
+ const sleepFixed = (ms) => new Promise(resolve => setTimeout(resolve, ms));
133
+
131
134
  const sleep = (ms, deviation = 1) => {
132
135
  let msWithDev = ((Math.random() * deviation) + 1) * ms;
133
136
  if (dryRun) msWithDev = Math.min(3000, msWithDev); // for dryRun, no need to wait so long
134
137
  logger.log('Waiting', (msWithDev / 1000).toFixed(2), 'sec');
135
- return new Promise(resolve => setTimeout(resolve, msWithDev));
138
+ return sleepFixed(msWithDev);
136
139
  };
137
140
 
138
141
  async function onImageLiked({ username, href }) {
@@ -279,7 +282,7 @@ const Instauto = async (db, browser, options) => {
279
282
  }
280
283
  }
281
284
  } catch (err) {
282
- logger.warn('Failed to get user data from page', err);
285
+ logger.warn(`Unable to get user data from page (${err.name}) - This is normal`);
283
286
  }
284
287
  return undefined;
285
288
  }
@@ -412,7 +415,11 @@ const Instauto = async (db, browser, options) => {
412
415
  }
413
416
 
414
417
  async function findUnfollowConfirmButton() {
415
- const elementHandles = await page.$x("//button[text()='Unfollow']");
418
+ let elementHandles = await page.$x("//button[text()='Unfollow']");
419
+ if (elementHandles.length > 0) return elementHandles[0];
420
+
421
+ // https://github.com/mifi/SimpleInstaBot/issues/191
422
+ elementHandles = await page.$x("//*[@role='button'][contains(.,'Unfollow')]");
416
423
  return elementHandles[0];
417
424
  }
418
425
 
@@ -570,7 +577,7 @@ const Instauto = async (db, browser, options) => {
570
577
  }
571
578
 
572
579
  /* eslint-disable no-undef */
573
- async function likeCurrentUserImagesPageCode({ dryRun: dryRunIn, likeImagesMin, likeImagesMax }) {
580
+ async function likeCurrentUserImagesPageCode({ dryRun: dryRunIn, likeImagesMin, likeImagesMax, shouldLikeMedia: shouldLikeMediaIn }) {
574
581
  const allImages = Array.from(document.getElementsByTagName('a')).filter(el => /instagram.com\/p\//.test(el.href));
575
582
 
576
583
  // eslint-disable-next-line no-shadow
@@ -629,12 +636,42 @@ const Instauto = async (db, browser, options) => {
629
636
 
630
637
  if (!foundClickable) throw new Error('Like button not found');
631
638
 
632
- if (!dryRunIn) {
633
- foundClickable.click();
639
+ const instautoLog2 = instautoLog;
640
+
641
+ // eslint-disable-next-line no-inner-declarations
642
+ function likeImage() {
643
+ if (shouldLikeMediaIn !== null && (typeof shouldLikeMediaIn === 'function')) {
644
+ const presentation = dialog.querySelector('article[role=presentation]');
645
+ const img = presentation.querySelector('img[alt^="Photo by "]');
646
+ const video = presentation.querySelector('video[type="video/mp4"]');
647
+ const mediaDesc = presentation.querySelector('[role=menuitem] h2 ~ div').textContent;
648
+ let mediaType; let src; let alt; let poster;
649
+ if (img) {
650
+ mediaType = 'image';
651
+ ({ src } = img);
652
+ ({ alt } = img);
653
+ } else if (video) {
654
+ mediaType = 'video';
655
+ ({ poster } = video);
656
+ ({ src } = video);
657
+ } else {
658
+ instautoLog2('Could not determin mediaType');
659
+ }
634
660
 
661
+ if (!shouldLikeMediaIn({ mediaType, mediaDesc, src, alt, poster })) {
662
+ instautoLog2(`shouldLikeMedia returned false for ${image.href}, skipping`);
663
+ return;
664
+ }
665
+ }
666
+
667
+ foundClickable.click();
635
668
  window.instautoOnImageLiked(image.href);
636
669
  }
637
670
 
671
+ if (!dryRunIn) {
672
+ likeImage();
673
+ }
674
+
638
675
  await window.instautoSleep(3000);
639
676
 
640
677
  const closeButtonChild = document.querySelector('svg[aria-label="Close"]');
@@ -669,7 +706,7 @@ const Instauto = async (db, browser, options) => {
669
706
  // Ignore already exists error
670
707
  }
671
708
 
672
- await page.evaluate(likeCurrentUserImagesPageCode, { dryRun, likeImagesMin, likeImagesMax });
709
+ await page.evaluate(likeCurrentUserImagesPageCode, { dryRun, likeImagesMin, likeImagesMax, shouldLikeMedia });
673
710
  }
674
711
 
675
712
  async function followUserRespectingRestrictions({ username, skipPrivate = false }) {
@@ -691,17 +728,17 @@ const Instauto = async (db, browser, options) => {
691
728
  return false;
692
729
  }
693
730
  if (
694
- (followUserMaxFollowers != null && followedByCount > followUserMaxFollowers) ||
695
- (followUserMaxFollowing != null && followsCount > followUserMaxFollowing) ||
696
- (followUserMinFollowers != null && followedByCount < followUserMinFollowers) ||
697
- (followUserMinFollowing != null && followsCount < followUserMinFollowing)
731
+ (followUserMaxFollowers != null && followedByCount > followUserMaxFollowers)
732
+ || (followUserMaxFollowing != null && followsCount > followUserMaxFollowing)
733
+ || (followUserMinFollowers != null && followedByCount < followUserMinFollowers)
734
+ || (followUserMinFollowing != null && followsCount < followUserMinFollowing)
698
735
  ) {
699
736
  logger.log('User has too many or too few followers or following, skipping.', 'followedByCount:', followedByCount, 'followsCount:', followsCount);
700
737
  return false;
701
738
  }
702
739
  if (
703
- (followUserRatioMax != null && ratio > followUserRatioMax) ||
704
- (followUserRatioMin != null && ratio < followUserRatioMin)
740
+ (followUserRatioMax != null && ratio > followUserRatioMax)
741
+ || (followUserRatioMin != null && ratio < followUserRatioMin)
705
742
  ) {
706
743
  logger.log('User has too many followers compared to follows or opposite, skipping');
707
744
  return false;
@@ -1003,7 +1040,7 @@ const Instauto = async (db, browser, options) => {
1003
1040
  await sleep(6000);
1004
1041
  }
1005
1042
 
1006
- await sleep(6000);
1043
+ await sleepFixed(10000);
1007
1044
 
1008
1045
  // Sometimes login button gets stuck with a spinner
1009
1046
  // https://github.com/mifi/SimpleInstaBot/issues/25
@@ -1137,9 +1174,9 @@ const Instauto = async (db, browser, options) => {
1137
1174
  });
1138
1175
 
1139
1176
  function condition(username) {
1140
- return getPrevFollowedUser(username) &&
1141
- !excludeUsers.includes(username) &&
1142
- (new Date().getTime() - getPrevFollowedUser(username).time) / (1000 * 60 * 60 * 24) > ageInDays;
1177
+ return getPrevFollowedUser(username)
1178
+ && !excludeUsers.includes(username)
1179
+ && (new Date().getTime() - getPrevFollowedUser(username).time) / (1000 * 60 * 60 * 24) > ageInDays;
1143
1180
  }
1144
1181
 
1145
1182
  return safelyUnfollowUserList(followingUsersGenerator, limit, condition);
@@ -1151,8 +1188,7 @@ const Instauto = async (db, browser, options) => {
1151
1188
  getFollowers: false,
1152
1189
  });
1153
1190
 
1154
- return allFollowing.filter(u =>
1155
- !getPrevFollowedUser(u) && !excludeUsers.includes(u));
1191
+ return allFollowing.filter(u => !getPrevFollowedUser(u) && !excludeUsers.includes(u));
1156
1192
  }
1157
1193
 
1158
1194
  return {