Skip to content

Instantly share code, notes, and snippets.

@shelldandy
Last active September 14, 2021 15:13
Show Gist options
  • Save shelldandy/a283ed9d1aedfa26542aea4c6da9593e to your computer and use it in GitHub Desktop.
Save shelldandy/a283ed9d1aedfa26542aea4c6da9593e to your computer and use it in GitHub Desktop.

Revisions

  1. shelldandy revised this gist Sep 14, 2021. 1 changed file with 10 additions and 1 deletion.
    11 changes: 10 additions & 1 deletion likes-cleaner.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,6 @@
    import Twitter from 'twitter-lite'
    import sleep from 'sleep'
    import chalk from 'chalk'
    import { promiser } from './utils.js'

    const options = {
    consumer_key: process.env.CONSUMER_KEY,
    @@ -12,6 +11,16 @@ const options = {

    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) {
  2. shelldandy revised this gist Sep 14, 2021. 1 changed file with 41 additions and 0 deletions.
    41 changes: 41 additions & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,41 @@
    - Create an app on apps.twitter.com
    - Grab the Consumer Key (API Key) and Consumer Secret (API Secret) from Keys and Access Tokens
    - Make sure you set the right access level for your app
    - If you want to use user-based authentication, grab the access token key and secret as well

    Make a package.json with the above packages:

    ```sh
    yarn add twitter-lite sleep chalk dotenv
    ```

    Create a `.env` file like the following:

    ```
    CONSUMER_KEY=xx
    CONSUMER_SECRET=xx
    ACCESS_TOKEN_KEY=xx
    ACCESS_TOKEN_SECRET=xx
    ```

    Replace the `xx` with your actual credentials, duh.

    If you're running a modern-ish version of node then you can use imports directly by adding this field on your `package.json`

    ```json
    {
    "type": "module",
    "scripts": {
    "start": "node -r dotenv/config index",
    "debug": "node inspect -r dotenv/config index"
    }
    }
    ```

    Also added some useful scripts.

    ```sh
    yarn start
    ```

    Boom, it will recursively clean likes until it finishes...
  3. shelldandy created this gist Sep 14, 2021.
    76 changes: 76 additions & 0 deletions likes-cleaner.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,76 @@
    import Twitter from 'twitter-lite'
    import sleep from 'sleep'
    import chalk from 'chalk'
    import { promiser } from './utils.js'

    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)

    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!!!')
    })()