El archivo app.js contendrá el código del servidor. Comienza importando las dependencias:
1234567var express =require("express");var app =express();var exphbs =require("express-handlebars");var config =require("./config");varHandlebars=require("handlebars");varTwit=require("twit");varPubNub=require("pubnub");
javascript
Luego, crea los objetos para trabajar con las APIs de Twitter y PubNub:
123456789101112varT=newTwit({ consumer_key: config.twitter.consumer_key, consumer_secret: config.twitter.consumer_secret, access_token: config.twitter.access_token, access_token_secret: config. twitter.access_token_secret});var pubnub =newPubNub({ ssl: config.pubnub.ssl, publishKey: config.pubnub.publish_key, subscribeKey: config.pubnub.subscribe_key});
javascript
En el archivo config.js, definimos los hashtags a rastrear con el carácter #, sin embargo, como vamos a usar estos tags como parámetros y en otros lugares, sería útil tener una versión de este arreglo sin este carácter:
123var tagsToTrack = config.hashtagsToTrack.map(function(val){return val.substr(1);});
javascript
A continuación, configure el Manillar y las vistas y el directorio público:
123456789var hbs = exphbs.create({ extname:".hbs"});app.set("views", __dirname +"/views");app.use(express.static(__dirname +"/public"));app.engine(".hbs", hbs.engine);app.set("view engine",".hbs");
javascript
Sin embargo, al renderizar la plantilla, necesitaremos saber si un determinado hashtag está activo (es parte del grupo de canales). Esto se puede hacer con una función de ayuda en el Manillar.
Este ayudante tomará como argumentos el hashtag y el grupo de hashtags activos (además del argumento de opciones requerido por el ayudante), y añadirá un atributo booleano (activo) para indicar si el hashtag está activo o no:
1234567891011121314var hbs = exphbs.create({ extname:".hbs", helpers:{active:function(hashtag, group, options){var data;if(options.data){ data =Handlebars. createFrame(options.data);} data.active= data && group.indexOf(hashtag)--> -1;return options.fn(hashtag,{ data: data });}}});
javascript
Al definir el ayudante en el objeto hbs, estará disponible para todas las vistas. Puedes saber más sobre los ayudantes aquí.
A continuación, nuestra aplicación proporcionará las siguientes rutas:
1234/ - La página para visualizar los tweets/admin - La página de administración/admin/add/:channel - El punto final para añadir un canal al grupo de canales de PubNub/admin/remove/:channel - El punto final para quitar un canal del grupo de canales de PubNub
Para mantener las cosas organizadas, vamos a tener un routes/index.js para configurar el / route y un routes/admin.js para configurar el resto de las rutas (verán el contenido de estos archivos en un momento). Para evitar crear los objetos que vamos a usar en estas rutas, vamos a configurarlas también a nivel de aplicación:
12345678app.set("pubnub", pubnub);app.set("tagsToTrack", tagsToTrack);var indexRoutes =require("./routes/index");var adminRoutes =require("./routes/admin");app.use("/", indexRoutes);app.use("/admin", adminRoutes);
javascript
Para configurar el servidor web, crea primero el grupo de canales:
123456789101112131415161718app.listen(config.port,function(){console.log("Servidor arriba y escuchando en el puerto %d", config.port);// Agregar canales al grupo pubnub.channelGroups. addChannels({ channels: tagsToTrack, channelGroup: config.channelGroup},function(status){if(status.error){console.log(JSON.stringify(status));}else{/// Success}});});
javascript
El Controlador de Flujo de PubNub le permite recibir mensajes en múltiples canales desde una sola conexión de red. Puede utilizarlo de dos maneras:
- Multiplexación. Permite suscribirse a 50 canales a través de un socket TCP.
- Grupos de canales. Permite crear grupos de canales a los que se puede suscribir con una sola llamada. El límite de canales por grupo es de 2.000, y cada conexión de cliente puede suscribirse a 10 grupos de canales.
En el código anterior, estás añadiendo a un grupo de canales los hashtags a rastrear, además de definir las llamadas de éxito y error. Cuando el grupo de canales se cree con éxito, recibirás un objeto como el siguiente:
12345{"error":false, "operation": "PNAddChannelsToGroupOperation", "statusCode":200}
javascript
Una vez creado el grupo de canales, añadamos el código para obtener los tweets del Twitter Stream API
12345/// Obtener tweets de los hashtags a trackvar stream =T.stream("statuses/filter",{ track: config.hashtagsToTrack});stream.on("tweet",function(tweet){console.log(tweet);});
javascript
Usando los estados/filtros del API, empezaremos a rastrear los tweets que contienen los hashtags configurados.
Los tweets se entregan como objetos JSON. Aquí hay una muestra de un objeto de tweet:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374{ created_at: $0027Mon Jul 04 05:06:34 +0000 2016$0027, id:749831746275930100, id_str:$0027749831746275930963$0027, text:$0027#Dios te ama. &amp; yo #te amo también:). $0027, fuente:$0027<a >IFTTT</a>$0027, truncado:false, in_reply_to_status_id:null, in_reply_to_status_id_str:null, in_reply_to_user_id:null, in_reply_to_user_id_str: null, in_reply_to_screen_name:null, user:{ id:4568541503, id_str:$00274568541503$0027, name:$0027Example$0027, screen_name:$0027example$0027,location:$0027New Jersey, USA$0027, url:$0027http://www. ejemplo. com$0027, descripción:$0027Mi descripción$0027,protected:false, verified:false, followers_count:18008, friends_count:5977, listed_count:356, favorites_count:2, statuses_count:216006, created_at: $0027Tue Dec 22 14:27:38 +0000 2015$0027, utc_offset:-25200, zona horaria:$0027Pacific Time (US & Canada)$0027, geo_enabled:false, lang:$0027en$0027, contributors_enabled:false, is_translator: false, profile_background_color:$0027F5F8FA$0027, profile_background_image_url:$0027$0027, profile_background_image_url_https:$0027$0027, profile_background_tile:false, profile_link_color: 2B7BB9$0027, profile_sidebar_border_color:$0027C0DEED$0027, profile_sidebar_fill_color:$0027DDEEF6$0027, profile_text_color:$0027333333$0027, profile_use_background_image:true, profile_image_url:$0027http://pbs. twimg.com/profile_images/679660186131369984/8lfidXI7_normal.png$0027, profile_image_url_https:$0027https://pbs.twimg.com/profile_images/679660186131369984/8lfidXI7_normal.png$0027, profile_banner_url:$0027https://pbs.twimg. com/profile_banners/4568541503/1450882189$0027, default_profile:true, default_profile_image:false, following:null, follow_request_sent:null, notifications:null}, geo:null, coordinates:null, place:null, contributors:null, is_quote_status:false, retweet_count:0, favorite_count:0, entities:{ hashtags: [{"texto": "Dios", "índices":[0,4]},{"texto": "amor", "índices":[24,29]}], urls:[], menciones de usuario:[], símbolos:[], medios:[[Objeto]]}, entidades_extendidas: { media:[[Objeto]]}, favorita:false, retweeted:false, posiblemente_sensitiva:false, filter_level:$0027low$0027, lang:$0027en$0027, timestamp_ms:$00271467608794169$0027}
javascript
Ahora, lo que tenemos que hacer es determinar a cuál de los hashtags rastreados pertenece el tweet.
Ya que el tweet puede contener más de una etiqueta de hachís (e incluso puede tener dos o más de los hachís que estamos rastreando), paremos en el primero que coincida con uno de nuestros hachís rastreados, y almacenémoslo en la variable del canal:
12345678910111213stream.on("tweet",function(tweet){var channel ="";// A qué hashtag pertenece el tweet?for(var index en tweet.entities. hashtags){var hashtag = tweet.entities.hashtags[index].text.toLowerCase();if(tagsToTrack.indexOf(hashtag)-1){ channel = hashtag;break;}}};
javascript
Una vez que tengamos el hashtag, publiquemos en el canal PubNub (que pertenece al grupo de canales) un objeto con los valores que vamos a utilizar en el cliente (fíjate en cómo se construye la URL del tweet):
1234567891011121314151617181920212223242526// Publicar tweet dataif(channel !==""){var obj ={ text: tweet.text, url: "https://twitter.com/"+ tweet.user.screen_name+"/status/"+ tweet. id_str, hashtag: channel }; pubnub.publish({ channel: channel, message: obj },function(status, response){if(status.error){console.log(status);}else{console.log(response);}});}
javascript
Una vez que el mensaje se publica con éxito, la llamada de retorno imprime en la consola un objeto como este:
123{ timetoken: "14715559578183158";}
javascript
Volviendo a las rutas, rutas/index.js contendrá el siguiente código:
1234567891011121314151617181920212223242526var express =require("express");var config =require("../config");var router = express.Router();router.get("/",function(req, res, next){ req.app.get("pubnub").channelGroups.listChannels({ channelGroup: config. channelGroup},function(status, response){if(status.error){console.log(JSON.stringify(status));return;} res.render("index",{ hashtagsToTrack: req.app.get("tagsToTrack"), hashtagsInGroup: response.channels, config: config });});});module.exports= router;
javascript
Cuando se solicite la ruta /, obtendremos los canales activos en el grupo en ese momento. El método listChannels devuelve un objeto como el siguiente en caso de éxito:
12345678910{"canales":["familia", "amor", "noticias", "programación", "cita", "hoy"]}
javascript
Noten que pasamos estos canales y otros objetos como parámetros para representar la vista:
1234567callback:function(m){ res.render($0027index$0027,{ hashtagsToTrack: req.app.get($0027tagsToTrack$0027), hashtagsInGroup: m.channels, config: config });},
javascript
Por otro lado, routes/admin.js contendrá el código a ejecutar cuando se solicite la ruta /admin (al igual que la ruta anterior):
123456789101112131415161718192021222324var express =require("express");var config =require("../config");var router = express.Router();router.get("/",function(req, res, next){ req.app.get("pubnub").channelGroups.listChannels({ channelGroup: config. channelGroup},function(status, response){if(status.error){console.log(JSON.stringify(status));return;} res.render("admin",{ hashtagsToTrack: req.app.get("tagsToTrack"), hashtagsInGroup: response.channels, config: config });});
javascript
Y las rutas para añadir y quitar canales:
123456789101112131415161718192021222324252627282930313233343536373839404142434445router.put("/add/:channel",function(req, res, next){ req.app.get("pubnub").channelGroups.addChannels({ channels:[req. params.channel], channelGroup: config.channelGroup},function(status){if(status.error){console.log(JSON.stringify(status)); res.json({ status: "Error"});}else{//console.log(JSON.stringify(m)); res. json({ status: "OK"});}});});router.put("/remove/:channel",function(req, res, next){ req.app.get("pubnub").channelGroups.removeChannels({ channels:[req.params.channel], channelGroup: config. channelGroup},function(status){if(status.error){console.log(JSON.stringify(status)); res.json({ status: "Error"});}else{//console.log(JSON.stringify(m)); res.json({ status: "OK"});}});});module.exports= router;
javascript
Y eso es todo. La siguiente sección explicará cómo funcionan las vistas (para el cliente y el administrador).