Cómo crear un bot para Twitter

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.

[code javascript]
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
});
[/code]
Y las funciones correspondientes, junto con el uso del módulo sleep para pausar la ejecución.
[code javascript]
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);
}
);
}
};
[/code]

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.

[code javascript]
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)
});
}
};
[/code]

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
[code javascript]
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 = [
»,
»,
»
];
[/code]
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.
[code javascript]
//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
};
}
[/code]
A continuación definiremos la función que se encargará de recorrer nuestro array de followers  y comprobar las restricciones mencionadas anteriormente.
[code javascript]
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);
});
}
})
}
[/code]
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.
[code javascript]
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’);
}
}
[/code]
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.
[code javascript]
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;
[/code]
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.
[code javascript]
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();
});
[/code]
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.