import Twitter from 'twitter-lite' import sleep from 'sleep' import chalk from 'chalk' const options = { consumer_key: process.env.CONSUMER_KEY, consumer_secret: process.env.CONSUMER_SECRET, access_token_key: process.env.ACCESS_TOKEN_KEY, access_token_secret: process.env.ACCESS_TOKEN_SECRET } const client = new Twitter(options) export const promiser = (promise, improved) => promise .then((data) => [null, data]) .catch((err) => { if (improved) { Object.assign(err, improved) } return [err] // which is same as [err, undefined]; }) const handleError = e => { if ('errors' in e) { if (e.errors[0].code === 88) { console.log('Rate limit will reset on', new Date(e._headers.get('x-rate-limit-reset') * 1000)) } else { console.log('API Related Error...') console.log(e.errors) } } else { console.log('non-API Error') console.log(e) } } const unlike = async tweet => { let next = 1 let remaining = 0 const [e, res] = await promiser(client.post('favorites/destroy', { id: tweet.id_str })) if (e) { console.log(chalk.red(`❌ - https://www.twitter.com/${tweet.user.screen_name}/status/${tweet.id_str}`)) handleError(e) return } const headers = res._headers remaining = parseInt(headers.get('x-rate-limit-remaining')) if (!isNaN(remaining) && remaining === 0) { console.log(chalk.cyan('Waiting')) next = parseInt(headers.get('x-rate-limit-reset')) - Date.now() next = next / 1000 } console.log(chalk.green(`✅ - https://www.twitter.com/${res.user.screen_name}/status/${res.id_str}`)) return next } const fetchLikes = async () => { const favs = await client.get('favorites/list', { count: 200 }) console.log(`${favs.length} favs found...`) return favs } const handleUnlikes = async favs => { for (let i = 0, len = favs.length; i < len; i++) { const next = await unlike(favs[i]) console.log(chalk.green(`Sleeping for ${next}s...`)) sleep.sleep(next) } return true } ;(async () => { let favs = await fetchLikes() while (favs && favs.length > 0) { await handleUnlikes(favs) favs = await fetchLikes() } console.log('Eskeler!!!') })()