No hace mucho fui víctima de cyberbulling con amenazas, insultos y elevadas menciones, retweets y favoritos en Twitter cuando el Gobierno Venezolano confundió mi nombre y profesión por alguien que según ellos es el webmaster de DolarToday.com en un programa de TV donde me dedicaron 15 minutos en la emisora del estado VTV.

Gracias a las experiencias en IRC le reste importancia pero aun persistía la oleada de interacciones que molestaban mis notificaciones en Twitter. Al principio pensé en simplemente proteger mi cuenta y dejar que esto pasara pero sentí que eso era lo que los atacantes querían, La alternativa era silenciar a estas cuentas pero dejar que le lean al mismo tiempo.

La tarea suena sencilla pero cuando tienes cientos de cuentas insultando, amenazando y cientos de cientos mas retuiteando cada minuto, se hace un poco tediosa la tarea así que decidí automatizar esto con este script:

import json
import requests
from requests_oauthlib import OAuth1
import sys
import csv
from time import sleep

whitelist = ['orvtech']

shitlist = ['amaia_roja', 'anat5', 'carollafra', 'contraofensiva',
            'correoorinoco', 'forocandanga', 'guerrillaragua',
            'hectorodriguez', 'izarradeverdad', 'jorgerpsuv',
           'jrodriguezpsuv', 'lahojillaentv', 'laradiodelsur',
            'maperezpirela', 'nicolasmaduro', 'prisciliano_alf',
            'thaivama', 'yndiratorregros', 'PatriciaDorta40']

#credentials from ghost account
consumer_key=''
consumer_secret=''
access_token_key=''
access_token_secret=''

#credentials from actual account
consumer_key2=''
consumer_secret2=''
access_token_key2=''
access_token_secret2=''

def get_retweets(tweetid):
  retweetdata={}
  handles=[]
  api_url="https://api.twitter.com/1.1/statuses/retweets/"+tweetid+".json"
  payload = {'count':'100'}
  auth = OAuth1(consumer_key, consumer_secret, access_token_key, access_token_secret)
  r = requests.get(api_url, stream=False, auth=auth, params=payload)
  try:
    if r.headers['x-rate-limit-remaining'] and r.headers['x-rate-limit-remaining'] == "0":
      print("We reached rate limit for ", api_url)
      print("Try again at", r.headers["x-rate-limit-reset"])
      quit()
  except KeyboardInterrupt:
      sys.exit()
  except:
     print "OK"
  retweetsObj = json.loads(r.content)
  for y in range(len(retweetsObj)):
    handles.append(retweetsObj[y]['user']['screen_name'])
  return handles

BLOCK_URL = 'https://api.twitter.com/1.1/blocks/create.json'
MUTE_URL = 'https://api.twitter.com/1.1/mutes/users/create.json'

def getTweets(usuarios):
   api_url="https://api.twitter.com/1.1/statuses/user_timeline.json"
   payload = {'screen_name': usuarios, 'count':'1', 'trim_user':'t', 'include_rts':'false'}
   auth = OAuth1(consumer_key, consumer_secret, access_token_key, access_token_secret)
   r = requests.get(api_url, stream=False, auth=auth, params=payload)
   statusObj = json.loads(r.content)
   return statusObj[0]['id']

def act_on_handle(api_url, auth, payload):
    try:
       r = requests.post(api_url, stream=False, auth=auth, params=payload)
       msgs = json.loads(r.content)
       print r.headers['status'] , payload
       if r.headers['x-rate-limit-remaining'] and r.headers['x-rate-limit-remaining'] == "0":
          print('We reached rate limit for {url}'.format(url=api_url))
          print('Try again at {reset}'.format(reset=r.headers["x-rate-limit-reset"]))
          sys.exit()
    except KeyboardInterrupt:
       sys.exit()
    except:
       pass

def main():
    for cuenta in shitlist:
       try:
         tweet = str(getTweets(cuenta))
         print "\nAnalizyng retweeters of" , cuenta , "TweetID:", tweet
         print "https://twitter.com/" + cuenta + "/status/" + tweet
         HANDLES = get_retweets(tweet)
         for user in HANDLES:
            if user not in whitelist:
              auth2 = OAuth1(consumer_key2, consumer_secret2, access_token_key2, access_token_secret2)
              payload = "screen_name=" + user
              #act_on_handle(BLOCK_URL, auth2, payload)
              act_on_handle(MUTE_URL, auth2, payload)
              sleep(1)
            else:
              print "YOU FOLLOW " , user , "WHO RETWEETED" , cuenta
              sleep(40)
         sleep(60)
       except KeyboardInterrupt:
         sys.exit()
       except:
         pass

if __name__ == '__main__':
    main()

Este script usa dos cuentas, La cuenta que esta siendo atacada la cual va a ser protegida y una segunda cuenta que es la que usamos para ver las interacciones de las cuentas que nos están atacando. Al momento de escribir este articulo, no es necesario usar la segunda cuenta pero en un futuro twitter podría prohibir que uno viera las interacciones de tweets de cuentas que no tiene en mudo o bloqueadas por el API así que decidí prepararme para eso. Como siempre los OAuth tokens y llaves las pueden obtener registrando sus apps en apps.twitter.com.

El programa lo que hace es buscar todos los tweets de una lista de cuentas que sabemos nos atacan y tomar acción contra quienes retuitean estos tweets, las acciones pueden ser bloquear y/o enmudecer.

Tras dejarlo correr un par de ciclos el resultado fue total normalidad en mi cuenta de Twitter. Ayudo un poco que los clusters de cuentas automatizadas fueron reportados y suspendidas de Twitter un par de días después.

Para la versión mas reciente de este programa, colaborar y reportar bugs pueden visitar el mi repositorio en GitHub.