Cómo crear un bot para Twitter

Nico Pons, nuestro compañero en prácticas y estudiante de DAM en Florida Universitaria, ha estado programando un bot para Twitter ¿queréis saber cómo lo ha hecho? Nos lo cuenta a continuación:

Vamos a crear un bot que simule el comportamiento de un usuario de Twitter que realiza follow y unfollow a otros usuarios.

Para ello hemos decidido usar javascript como lenguaje de programación junto con Node.js debido a la enorme cantidad de módulos que nos harán el desarrollo más fácil.

Antes de empezar deberemos crear una app de Twitter (aquí) y tener instalado Node.js en nuestra máquina, una vez esté todo listo procederemos a instalar los módulos necesarios en nuestro proyecto:

  • Express: framework de desarrollo web para Node, sobre el que lanzaremos nuestro bot.
  • Twitter: cliente de Twitter para Node que nos facilitara las tareas a la hora de hacer las llamadas al api de twitter .
  • Mysql: cliente de Mysql para Node con el que crear conexiones a la base de datos.
  • Cron: temporizador sobre el que indicaremos cuándo realizar cada acción
  • Sleep: pausar la ejecución, en nuestro caso para no llegar al límite de llamadas que nos permite realizar el API de Twitter.

Cuando tengamos todo listo vamos a ponernos manos a la obra. Empezaremos creando un fichero llamado bot.js que se encargará de realizar las llamadas necesarias al API de Twitter que serán la de follow y unfollow a un usuario, obtener los followers del usuario, obtener la información un usuario por su id y si un usuario nos sigue.

Para ello debemos crear un cliente de Twitter usando el módulo de Twitter.

var twitter = require('twitter');

var MY_USER_ID = "" // id de nuestra cuenta
var client = new twitter({
    consumer_key: "", //apikey de nuestra app
    consumer_secret: "", //apikey secret de nuestra app
    access_token_key: "", //token de nuestra app
    access_token_secret: "" //token secret de nuestra app
});

Y las funciones correspondientes, junto con el uso del módulo sleep para pausar la ejecución.

module.exports.bot = {
        // follow a un usuario
    followUser: function (id, callback) {
        sleep.sleep(10);
        client.post('friendships/create',
            {user_id: id},
            function (err, data, res) {
                callback(err, data);
            }
        );
    },
    // unfollow a un usuario
    unfollowUser: function (id, callback) {
        sleep.sleep(10);
        client.post('friendships/destroy',
            {user_id: id},
            function (error, data, response) {
                callback(error, data);
            }
        );
    },
 // seguidores de un usuario
    followersFromUser: function (name, cursor, callback) {
        sleep.sleep(10);
        client.get('followers/list',
            {
                screen_name: name,
                cursor: cursor,
                count: 200,
                include_user_entities: false,
                skip_status: true
            },
            function (error, data, response) {
                callback(error, data);
            }
        );
    },
    // obtener la informacion de un usuario
    getUserById: function (id, callback) {
        sleep.sleep(10);
        client.get('users/show',
            {user_id: id},
            function (error, data, response) {
                callback(error, data);
            }
        );
    },
    // comprobar si un usuario me sigue
    isFollowingMe: function (id, callback) {
        sleep.sleep(10);
        client.get('friendships/show',
            {
                source_id: MY_USER_ID,
                target_id: id
            },
            function (error, data, response) {
                callback(error, data);
            }
        );
    }
};

Cabe mencionar que para cada petición se necesitan unos parámetros específicos disponibles en la documentación del api de twitter.

El siguiente paso será crear nuestra conexión con la base de datos en la que guardaremos los usuarios a los que hemos hecho follow junto con la fecha correspondiente ya que twitter no nos proporciona esta información, para transcurrido un tiempo, comprobar si nos han devuelto el follow o no.

Para ello vamos a crear un fichero llamado bd.js donde configuraremos la conexión con base de datos e implementaremos la función correspondientes para realizar consultas, para ello tan solo nos bastará con añadir unas cuantas líneas tal y como se explica en la documentación de módulo de mysql.

var MySQL = require('mysql');

var config = {
    host: '', // nombre del host
    user: '', // nombre de usuario
    password: '', // constraseña del usuario
    database: '' // nombre de la base de datos
};

var connection;

module.exports.bd = {
        // iniciar la conexion
    connect: function () {
        connection = MySQL.createConnection(config);
    },
    // desconectar
    disconnect: function () {
        connection.disconnect();
    },
    // realizacion de consultas
    query: function (statement, callback) {
        connection.query(statement, function (err, data, fields) {
            callback(err, data)
        });
    }
};

Ahora vamos a implementar la lógica que tendrá nuestro bot, en este caso vamos a tener una lista con usuarios de los cuales obtendremos sus followers y haremos follow a una cantidad de usuarios de dicha lista diariamente. Una vez finalizado con los followers de un usuario, saltará al siguiente usuario de nuestra lista y así sucesivamente.

Para hacer follow a un usuario deberá tener más de 300 seguidores, poseer descripción e imagen de perfil y cuyo perfil sea público, se podrían añadir más restricciones como por ejemplo el país de donde procede, cantidad de twits pero con estos será suficiente por ahora.

Crearemos un nuevo fichero llamado follow.js y definiremos las siguientes variables

var bd = require('./bd').bd;
var sleep = require('sleep');
var bot = require('./bot').bot;

var maxFollow = 100; // cantidad de usuarios a seguir
// imagenes de perfil por defecto
var defImgProfile = [
    "http://abs.twimg.com/sticky/default_profile_images/default_profile_1_normal.png",
    "http://abs.twimg.com/sticky/default_profile_images/default_profile_2_normal.png",
    "http://abs.twimg.com/sticky/default_profile_images/default_profile_3_normal.png",
    "http://abs.twimg.com/sticky/default_profile_images/default_profile_4_normal.png",
    "http://abs.twimg.com/sticky/default_profile_images/default_profile_5_normal.png",
    "http://abs.twimg.com/sticky/default_profile_images/default_profile_6_normal.png"
];
// lista de usuarios de los que obtener los seguidores
var users = [
    '',
    '',
    ''
];

El siguiente paso es crear las funciones que manipulan los datos que nos devuelve el api de twitter, tendremos el método nextPage que se encargará de paginar entre los json de followers de cada usuario y se encargará de llamar al método followersFromUser de nuestro bot, obtener los datos necesarios de cada usuario y guardarlo en el array followers.

//recibe el nombre del usuario sobre el que obtener los seguidores
function nextPage(name) {
        // llamamos a la funcion que devuelve los followers del usuario
    bot.followersFromUser(name, cursor, function (err, data) {
        if (err) console.log(err);
        else {
            posFollow = 0; // reseteamos la posicion en la lista
            for (var i = 0; i < data.users.length; i++) {
                followers[i] = getUser(data.users[i]); // filtramos la informacion de cada usuario
                nextCursor = data.next_cursor_str; // guardamos el siguiente cursor
            }
        }
    });
}

function getUser(data) {
    return {
        id_str: data.id_str,
        screen_name: data.screen_name,
        desc: data.description,
        profile: data.protected,
        followers: data.followers_count,
        image: data.profile_image_url,
        imFollowing: data.following
    };
}

A continuación definiremos la función que se encargará de recorrer nuestro array de followers  y comprobar las restricciones mencionadas anteriormente.

function checkUsers(name) {
    var i = posFollow;
    var count = countFollow;
    // recorremos los followers i comprobamos los requisitos para hacer el follow
    while (count < maxFollow && i < followers.length) {
        var user = followers[i];
        if ((!user.profile) &&
            (user.followers >= 300) &&
            (defImgProfile.indexOf(user.image) === -1) &&
            (user.description != "") &&
            (!user.imFollowing)) {
                            // si cumple los requisitos hacemos follow
                count++;
                follow(user);
        }
        i++;
    }
    // actualizamos los valores de las variables
    countFollow = count;
    posFollow = i;
    // si ha terminado de leer el los followers pasa a la siguiente pagina
    if (posFollow >= followers.length) {
        cursor = nextCursor;
        nextPage(name);
    }
    // si ha realizado todos los follows indicados reseteamos el contador
    if (countFollow >= maxFollow) {
        countFollow = 0;
    }
}

// llamada a la funcion del bot para realizar el follow
function follow(user) {
    bot.followUser(user.id_str, function (err, data) {
        if (err) console.log(new Date(), err);
        else {
            var follow = data;
            var sql = "insert into users(user_id, follow_date, user_screen_name, user_name) " +
                "values ('" + data.id_str + "', now(),'" + data.screen_name + "','" + data.name + "')";
            bd.query(sql, function (err, data) {
                if (err) console.log(new Date(), err);
                else console.log(new Date(), 'follow', follow.screen_name);
            });
        }
    })
}

Además hemos añadido la función de follow que llama al método follow de nuestro bot e insertar los datos en nuestra base de datos si se ha realizado el follow correctamente.

Solo nos falta añadir la función start que será el punto de partida de nuestro follow y comprobará si ya se han recorrido todos los followers de un usuario y paginar el json o seguir comprobando el actual.

function start() {
    // comprueba que no se haya llegado al final de la lista de usuarios
    if (posUser < users.length - 1) {
        if (posFollow === followers.length) {
            cursor = nextCursor;
            // comprueba que no sea el ultimo json
            if (cursor.localeCompare('0') === 0) {
                posUser++;
                console.log(new Date(), 'next user', users[posUser]);
            }
            nextPage(users[posUser]);
        }
        else {
            checkUsers(users[posUser]);
        }
    }
    else {
        console.log(new Date(), 'users list end');
    }
}

Con esto ya tenemos nuestra lógica para hacer follow, tan solo queda es implementar la lógica para hacer el unfollow.

Crearemos otro fichero llamado unfollow.js con la función start que consultará sobre nuestra base de datos los usuarios que hemos seguido en un periodo de tiempo y comprobará si estos nos han devuelto el follow y en el caso de no ser así, hacer unfollow.

var bd = require('./bd').bd;
var bot = require('./bot').bot;

var interval = 5;

function start() {
    var sql = "select * from users where follow_date < date_add(now(), INTERVAL -" + interval + " day)";
    bd.query(sql, function (err, data) {
            // recorremos el resultado de la consulta
        for (var i = 0; i < data.length; i++) {
            var user = data[i];
            // comprobamos si nos sigue el usuario
            bot.isFollowingMe(user.user_id, function (err, data) {
                if (err) console.log(new Date(), err);
                else {
                    var rel = data.relationship; // true si nos sigue
                    if (!rel.target.following) unfollow(rel.target); // si no nos sigue le hacemos unfollow
                }
            });
        }
    });
}

// llama a la funcion unfollow del bot
function unfollow(user) {
    bot.unfollowUser(user.id_str, function (err, data) {
        if (err) console.log(new Date(), err);
        else console.log(new Date(), 'unfollow', data.screen_name);
    });
}

module.exports.start = start;

Como extra hemos añadido una función unfollow que se encargará de llamar al método unfollow de nuestro bot.

Para finalizar con nuestro bot añadiremos el punto de partida de nuestra aplicación, esto lo haremos desde nuestro fichero app.js en el que importamos los módulos de Express y Cron mencionados anteriormente y crearemos un servidor http sobre el que funcionará nuestro bot y además añadiremos la posibilidad de que nuestro bot se ejecute a una hora determinada utilizaremos Cron creando una instancia e indicando a qué hora queremos que se ejecuten el follow y el unfollow.

var bd = require('./bd').bd;
var follow = require('./follow');
var unfollow = require('./unfollow');
var express = require('express');
var cron = require('cron').CronJob;

var app = express();

app.listen(8001, function () {
        // configuracion para hacer unfollow a las 00:00
    var cronUnfollow = new cron({
        cronTime: '00 00 00 * * *', // SS, MM, HH, dd, mm, ww
        onTick: function () {
            unfollow.start();
        },
        start: false
    });
    // configuracion para hacer el follow a las 12:00 y las 18:00
    var cronFollow = new cron({
        cronTime: '00 00 12,18 * * *', // SS, MM, HH, dd, mm, ww
        onTick: function () {
            follow.start();
        },
        start: false
    });
    // iniciamos los cron
    cronFollow.start();
    cronUnfollow.start();
});

Y con esto y un bizcocho, ya hemos creado un bot para conseguir seguidores en nuestra cuenta de twitter. El siguiente paso sería hacer un seguimiento de cuántos usuarios nos siguen y guardar la información en la base de datos o enviar mensajes de agradecimiento a nuestros nuevos seguidores.

 

 

Paula Mascarós

Marketing Manager GeeksHubs

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *