Skip to content

Instantly share code, notes, and snippets.

@kutyel
Created December 19, 2017 13:48
Show Gist options
  • Save kutyel/f50f1d4d917cf6d1e944f708f6e77d82 to your computer and use it in GitHub Desktop.
Save kutyel/f50f1d4d917cf6d1e944f708f6e77d82 to your computer and use it in GitHub Desktop.
Twitter Unfollow Bot
'use strict'
require('now-env')
const Twit = require('twit')
const Task = require('data.task')
const Maybe = require('data.maybe')
const bot = new Twit({
consumer_key: process.env.CONSUMER_KEY,
consumer_secret: process.env.CONSUMER_SECRET,
access_token: process.env.ACCESS_TOKEN,
access_token_secret: process.env.ACCESS_TOKEN_SECRET,
timeout_ms: 60 * 1000
})
// #region Helpers
const get = (url, opts = { count: 200 }) =>
new Task((rej, res) =>
bot.get(url, opts, (err, data, response) => (err ? rej(err) : res(data)))
)
const post = text =>
new Task((rej, res) =>
bot.post(
'direct_messages/new',
{
screen_name: 'flaviocorpa',
text
},
(err, data, response) => (err ? rej(err) : res(data))
)
)
const sleep = ms => new Task((rej, res) => setTimeout(res, ms))
const diff = xs => xy => xs.filter(x => !xy.includes(x))
// #endregion
// TODO: this should be recursive (using a `cursor` to get all the followers)
const getFollowers = get('followers/list').map(data =>
data.users.map(user => user.screen_name)
)
Maybe.of(diff)
.ap(getFollowers)
// .ap(sleep(15 * 60 * 1000)) // TODO: how to delay both Tasks?
.ap(getFollowers)
.fork(console.error, console.log) // TODO: apply the `post` method to the list of unfollows
'use strict'
require('now-env')
const Twit = require('twit')
const bot = new Twit({
consumer_key: process.env.CONSUMER_KEY,
consumer_secret: process.env.CONSUMER_SECRET,
access_token: process.env.ACCESS_TOKEN,
access_token_secret: process.env.ACCESS_TOKEN_SECRET,
timeout_ms: 60 * 1000
})
const sleep = ms => new Promise((resolve, reject) => setTimeout(resolve, ms))
const diff = (xs, xy) => xs.filter(x => !xy.includes(x))
const getUsers = async (all = [], cursor = -1) => {
try {
const { data: { users = [], next_cursor_str: nextCursor } } = await bot.get('followers/list', {
count: 200,
cursor
})
all = [...all, ...users.map(x => x.screen_name)]
return nextCursor && nextCursor === '0' ? all : getUsers(all, nextCursor)
} catch (err) {
console.error(err)
return []
}
}
const main = async () => {
const oldFollowers = await getUsers()
await sleep(15 * 60 * 1000)
const currentFollowers = await getUsers()
const unfollows = diff(oldFollowers, currentFollowers)
unfollows.forEach(user =>
bot.post('direct_messages/new', {
screen_name: 'flaviocorpa',
text: `User @${user} stopped following you!`
})
)
}
module.exports = () => setInterval(() => main(), 15 * 60 * 1000)
@kutyel
Copy link
Author

kutyel commented Dec 19, 2017

Awesome, huge thanks!!! 👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment