Getting Data from a Weather API to a Twitter Bot - node.js

I'm setting up a Twitter bot to tweet out a city's temperature, I got the API but I can't seem to hook it on my bot.js file
I tried changing the variables but nothing seems to work.
var Twit = require('twit');
var config = require('./config');
var T = new Twit(config);
gotData();
function setup() {
loadJSON("http://api.apixu.com/v1/current.json?key=7165704df08340e9b00213540192507&q=Colombo", gotData);
}
function gotData(data) {
console.log('Weather Data Retrieved...')
var r = data.current[2];
var tweet = {
status: 'here is ' + r + ' temperature test '
}
T.post('statuses/update', tweet);
}
TypeError: Cannot read property 'current' of undefined

Your call to gotData() does not pass a data argument so when the gotData function attempts to access data.current[2] data is undefined. By the looks of your code you just need to change the line gotData(); to setup();

Related

using split in a module node.js

var telegram = require('telegram-bot-api');
var api = new telegram({
token: '',
updates: {
enabled: true,
get_interval: 1000
}
});
api.on('message', function(message){
var chat_id = message.chat.id;
var str = message.text;
var word = str.split(" ");
var yr = word[1].split("/");
above is my code, use the telegram-bot-api. Problem is the "split", when the code run, there is error: "TypeError: Cannot read property 'split' of undefined". How can I use split in a module?
thank you
It sounds like either the variable str is undefined or alternatively the value word[1] is undefined. Split works fine in the node environment. I would test it out using some console.logs in the api.on callback. i.e console.log('str>>>', str) console.log('word>>>', word[1])

How to unpack an google.protobuf.Any type in gRPC nodejs client?

My protobuf file is like this:
syntax = "proto3"; import "google/protobuf/any.proto";
service RoomService {
getTestAny (Hotelid) returns (google.protobuf.Any); }
message Hotelid {
string hotelid = 1;
}
message HtlInDate {
Hotelid hotelid = 1;
string date = 2;
}
My java-gRPC-server code is like that:
#Override
public void getTestAny(Roomservice.Hotelid request, StreamObserver<Any> responseObserver) {
Roomservice.Hotelid hotelid = Roomservice.Hotelid.newBuilder()
.setHotelid("This is Hotelid")
.build();
Roomservice.HtlInDate htlDate = Roomservice.HtlInDate.newBuilder()
.setHotelid(hotelid)
.setDate("This is Data")
.build();
responseObserver.onNext(Any.pack(htlDate));
responseObserver.onCompleted();
}
And I make a request from a nodejs-gRPC-client, which code is like that:
function () {
var client = new services.RoomServiceClient('localhost:6565',
grpc.credentials.createInsecure());
var request = new messages.Hotelid();
var hotelid = "ignore";
request.setHotelid(hotelid);
var call = client.getTestAny(request, function (err, response) {
var obj = response.toObject();
console.log(obj);
});
}
The response in nodejs-gRPC-client is a type of Any. And it contains a data array:
array:["type.googleapis.com/HtlInDate", Uint8Array[10,17,10...]]
I try to use response.toObject() to get HtlInDate instance but I just get like this:
obj:{
typeUrl:"type.googleapis.com/HtlInDate",
value:"ChEKD1RoaXMgaXMgSG90ZWxpZBIMVGhpcyBpcyBEYXRh"
}
So how can I unpack the Any type response and get the HtlInDate instance exactly? Thanks a lot if you have any idea about this!
Currently, the google.protobuf.Any type is not supported in Node.js, either in Protobuf.js, which gRPC uses by default, or by google-protobuf, which is the official first party protobuf implementation.
From documentation:
https://developers.google.com/protocol-buffers/docs/reference/javascript-generated#message
// Storing an arbitrary message type in Any.
const status = new proto.foo.ErrorStatus();
const any = new Any();
const binarySerialized = ...;
any.pack(binarySerialized, 'foo.Bar');
console.log(any.getTypeName()); // foo.Bar
// Reading an arbitrary message from Any.
const bar = any.unpack(proto.foo.Bar.deserializeBinary, 'foo.Bar');
Please take a note that for browser support you need to use webpack(probably with babel loader) or browserify
As found in google-protobuf tests Any is bundled with pack and unpack functions.
Your code could be unpacked like this:
function () {
var client = new services.RoomServiceClient('localhost:6565',
grpc.credentials.createInsecure());
var request = new messages.Hotelid();
var hotelid = "ignore";
request.setHotelid(hotelid);
var call = client.getTestAny(request, function (err, response) {
var obj = response.toObject();
console.log('Any content', obj);
var date = response.unpack(messages.HtlInDate.deserializeBinary, response.getTypeName());
console.log('HtlInDate', date.toObject());
});
}
This will deserialize the bytes received in the Any object.
You could also build some Any using pack function for wrapping TypeUrl and Value:
var someAny = new Any();
someAny.pack(date.serializeBinary(), 'HtlInDate')

Cheerio scraping returning only two rows

So I tested my scraping on a static HTML file before adding it to my Node app.
The problem is that it's not returning all the rows.
On the site:
$('#sport tr').length
//Returns 13
In Cheerio:
$('#sport tr').length
//Returns 2
I'm stumped, here is the code I'm using. I've contained the URL as proof, so you can visit it yourself if you wish.
I'm suspecting it's something to do with var $ = cheerio.load(html); however I'm not experienced in Cheerio to say outright that's the problem.
var express = require('express');
var fs = require('fs');
var request = require('request');
var cheerio = require('cheerio');
var app = express();
app.get('/scrape', function(req, res){
var url = 'http://www.olbg.com/football.php';
var json = [];
request(url, function(error, response, html){
if(!error){
var $ = cheerio.load(html);
console.log($('#sport tr').length);
var headers = [];
$('#sport tr th').each(function(i, th) {
var text = $(th).text();
if (text.trim() !== "") {
headers[i] = text.replace(/[\t\n\r\s]/mgi, '');
}
});
$('#sport tr').each(function(i, tr) {
// skip if header
if (!$(tr).is('th')) {
var temp = {};
temp["Event"] = $(tr).find('td').eq(0).text().trim();
temp["TopSelection"] = $(tr).find('td').eq(1).text().trim();
temp["BookieOdds"] = $(tr).find('td').eq(2).text().trim();
temp["OLBGRating"] = $(tr).find('td').eq(3).find('img').length;
if (temp["Event"] !== "" || temp["TopSelection"] !== ""){
json.push(temp);
}
}
});
}
// To write to the system we will use the built in 'fs' library.
// In this example we will pass 3 parameters to the writeFile function
// Parameter 1 : output.json - this is what the created filename will be called
// Parameter 2 : JSON.stringify(json, null, 4) - the data to write, here we do an extra step by calling JSON.stringify to make our JSON easier to read
// Parameter 3 : callback function - a callback function to let us know the status of our function
fs.writeFile('output.json', JSON.stringify(json), function(err){
console.log('File successfully written!');
})
// Finally, we'll just send out a message to the browser reminding you that this app does not have a UI.
res.send(json);
});
});
app.listen("8081");
console.log("Magic happens on port 8081");
exports = module.exports = app;
The reason that you're not getting the expected result is because the (table) html on that page is mangled. If you look at the second <td> in the second <tr> of the table#sport, you'll see an "extra" </td>. This causes the <td> that the table#sport is inside to close (and an implicit closing of table#sport) on some parsers because that is the closest open <td>. So that is why the parser reports only 2 <tr>s instead of 13. The other <tr>s you're expecting are now outside of table#sport.
Probably your best bet is to pass the html through an HTML tidying program/script (e.g. this one with the clean option enabled) first before passing it to cheerio. After that, your selector should return the elements you're probably expecting.

Unexpected value for 'this' in express.js instantiated controllers

'this' does not appear to refer to the instantiated budget controller object. Instead it seems to refer to the global object. Does anyone know why this is?
I've defined a budget model. Injected into the controller and I'm attempting to simply generate a random 6 char string when I hit /budgets in my app. Instead this.DEFAULT_SLUG_LENGTH is undefined and I can't figure out why.
This is a dumbed down test case illustrating the issue with 'this'. I have a similar problem when referencing the injected this.budget within another function to query the db based on the slug value.
//models/budget.js
var Schema = require('jugglingdb').Schema;
var schema = new Schema('postgres',{url:process.env.DATABASE_URL});
var Budget = schema.define('budgets',{
total: Number,
slug: String
});
module.exports = Budget;
====================
//controllers/budget.js
function BudgetController (budget) {
this.budget = budget;
};
BudgetController.prototype.DEFAULT_SLUG_LENGTH = 6;
BudgetController.prototype.generateSlug = function (req,res) {
var slug = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < this.DEFAULT_SLUG_LENGTH; i++) {
slug += possible.charAt(Math.floor(Math.random() * possible.length));
}
res.send(slug);
};
module.exports = BudgetController;
===================
//app.js
var express = require('express');
var app = express();
app.use(express.bodyParser());
// models
var Budget = require('./models/budget');
// controllers
var BudgetController = require('./controllers/budget');
var budgetCtrl = new BudgetController(Budget);
// routes
app.get('/budgets',budgetCtrl.generateSlug);
app.listen(process.env.PORT || 4730);
If I manually instantiate the model/controller in the node repl, the generateSlug method works fine. If I restructure my code so that the BudgetController is a function that returns an object {} with methods, that seems to work fine. Is there some issue with my use of prototype/new ?
express takes functions and invokes them without a preceding object, so if you want to use an object method bound to a specific this as an express route handler function, you need to bind it:
app.get('/budgets', budgetCtrl.generateSlug.bind(budgetCtrl));

Unable to create Spotify app playlist view

I'm trying to display a simple playlist view in my Spotify app with the following code:
sp = getSpotifyApi(1);
var m = sp.require("sp://import/scripts/api/models");
var v = sp.require("sp://import/scripts/api/views");
var jq = sp.require('sp://XXX/jquery/jquery-1.7.1.min');
var pl = m.Playlist.fromURI('spotify:user:d3marcus:playlist:4zPZzImEYkUOVBvxIo42im');
var player = new v.Player();
player.track = pl.get(0);
player.context = pl;
var list = new v.List(pl);
$('XXX').append(list.node);
This will result in an empty list view and an error caught in sp://import/scripts/language.js:44: "Uncaught TypeError: Cannot read property 'length' of undefined"
Any suggestions?
I would say you are getting this error because the playlist has not yet loaded when you do pl.get(0). To make sure the playlist model has loaded you could either do
pl = m.Playlist.fromURI('spotify:user:d3marcus:playlist:4zPZzImEYkUOVBvxIo42im');
pl.observe(models.EVENT.LOAD, function() {
player.track = pl.get(0);
...
});
or
m.Playlist.fromURI("spotify:user:d3marcus:playlist:4zPZzImEYkUOVBvxIo42im", function(pl) {
player.track = pl.get(0);
...
});
I'm not sure, but could you try this :
$('YYY').append($(player.node));
$('XXX').append($(list.node));
instead of
$('XXX').append(list.node);
let us know...
For the 1.0 API:
require([
'$api/models',
'$views/list#List'
], function (models,List) {
var addList = function(list) {
list.load('tracks').done(function(list) {
list.tracks.snapshot().done(function(trackSnapshot){
// Make the playlist view
var multiple_tracks_player = document.getElementById('addedTracksList');
var playableList = List.forPlaylist(list);
multiple_tracks_player.appendChild(playableList.node);
playableList.init();
});
});
}
exports.addList = addList;
}
// Example of use:
addList(models.Playlist.fromURI(...))
I've tested it as used above, so it should work.
I found this in the tutorial-app available on github under "Playing music"-section -> "Play a list of tracks"
I hope this is helpfull.

Resources