Created
August 20, 2020 22:09
-
-
Save PLhery/c59e3a4d1af5e38e9ac89fa1725cabda to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { IgApiClient } from 'instagram-private-api'; | |
// @ts-ignore (dependency not typed) | |
import Instagram from 'instagram-web-api' | |
import * as dotenv from 'dotenv'; | |
dotenv.config({ path: __dirname+'/.env' }); | |
const username = process.env.IG_USERNAME || ''; | |
const password = process.env.IG_PASSWORD || ''; | |
const INTERVAL_BETWEEN_CHECKS = 10*60*1000; // pause in ms between each checks (a check lasts ~4sec/user) | |
interface INinjaUser { | |
followers: number[]; // todo following dates | |
} | |
interface IInstaUser { | |
id: string; | |
username: string; | |
full_name: string; | |
profile_pic_url: string; | |
is_verified: boolean; | |
followed_by_viewer: boolean; | |
requested_by_viewer: boolean; | |
} | |
// TODO put these in a database to work after a downtime | |
const ninjaUsers: {[key: number]: INinjaUser} = {}; | |
const usernamesById: {[key: number]: string} = {}; | |
const mobileClient = new IgApiClient(); | |
mobileClient.state.generateDevice(String(username)); | |
const webClient = new Instagram({ username, password }); | |
async function getAllFollowers(userId: number): Promise<number[]> { | |
const followers: number[] = []; | |
let cursor; | |
while (true) { | |
const response: any = await webClient.getFollowers({userId, after: cursor}); | |
followers.push(...response.data.map((user: IInstaUser) => Number(user.id))); | |
response.data.forEach((user: IInstaUser) => usernamesById[Number(user.id)] = user.username); | |
console.log(`--fetching followers ${followers.length}/${response.count}...`); | |
if (!response.page_info.has_next_page) { | |
break; | |
} | |
cursor = response.page_info.end_cursor; | |
} | |
return followers | |
} | |
async function checkUnfollowers(userId: number) { | |
const username = usernamesById[userId]; | |
console.log(`\nChecking @${username}'s unfollowers...`); | |
const followers = await getAllFollowers(userId); | |
const followersSet = new Set(followers); | |
const ninjaUser = ninjaUsers[userId]; | |
if (ninjaUser) { | |
const formerFollowers = ninjaUser.followers; | |
const unfollowers = formerFollowers.filter(id => !followersSet.has(id)); | |
for (const unfollowerId of unfollowers) { | |
const unfollowerUsername = usernamesById[unfollowerId]; | |
console.log(`Someone unfollowed @${username} : ${unfollowerId} ${unfollowerUsername}`); | |
await mobileClient.directThread.broadcast({ | |
userIds: [userId], | |
item: 'text', | |
form: { | |
text: `@${unfollowerUsername} unfollowed you 👋`, | |
}, | |
}); | |
console.log(`notification sent.`); | |
} | |
} | |
ninjaUsers[userId] = { | |
followers, | |
} | |
} | |
async function loginAndRun() { | |
console.log('logging in...'); | |
// await mobileClient.simulate.preLoginFlow(); | |
await mobileClient.account.login(username, password); | |
// await mobileClient.simulate.postLoginFlow(); | |
const user = await webClient.login(); | |
console.log(user); | |
await checkAllUsers(Number(user.userId)); | |
} | |
async function checkAllUsers(userId: number) { | |
console.log(new Date(), 'checking all unfollowers'); | |
const users = await getAllFollowers(userId); | |
console.log(`${users.length} users found`); | |
const start = Date.now(); | |
try { | |
for (const userId of users) { | |
await checkUnfollowers(userId); | |
} | |
console.log(`All accounts checked in ${Date.now() - start}ms`); | |
} catch (error) { | |
console.log(`An error occured after ${Date.now() - start}ms, skipping this check`); | |
console.error(error); | |
} | |
setTimeout(() => checkAllUsers(userId).catch(err => console.error(err.stack)), INTERVAL_BETWEEN_CHECKS); | |
} | |
loginAndRun().catch(err => console.error(err.stack)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment