NodeJs / Google Firebase functions string methods not working - javascript

I have a Google Assistant app that uses some API's to retrieve and deliver bus arrival times for my local university. The thing is the API returns the arrival times in a string like this:
"2018-51-02T06:51:11"
I try to maniuplate that string with the slice and indexOf functions that exist within javascript to just get the final time portion of the string, the exact code is
finalString = departure.slice(departure.indexOf('T')+1, departure.length);
but at the end of it all it still only prints out and responds with the original string. Offline and local on my machine that code works, but when uploaded to Firebase Functions it no longer works. Any help with this issue?
app.intent("wheres the catabus", (conv, {route}) => {
var routeDetails;
var closest_stop;
var finalString;
return cataAPIService.getRouteDetails(route)
.then((routeData) => {
routeDetails = routeData;
closest_stop = cataAPIService.findClosestStop(routeData, conv.device.location);
return cataAPIService.getStopDetails(closest_stop.StopId)
})
.then((stopData) => {
var departure = cataAPIService.getEstimatedStopDeparture(routeDetails, stopData);
finalString = departure.slice(departure.indexOf('T')+1, departure.length);
conv.ask('The closest stop to you is at ' + closest_stop.Name + '. The next departure is scheduled for ' + finalString);
})
.catch((error) => {
console.log(error);
conv.ask("I can't get that information right now, please try again.");
});
});

I wasn't able to duplicate your problem on Firebase Cloud Functions using node.js 6 and the following code:
var departure="2018-51-02T06:51:11";
var finalString = departure.slice(departure.indexOf('T')+1, departure.length);
console.log('finalstring',finalString);
As expected, it sent the following to the logs:
finalstring 06:51:11
If you show the complete code that is causing the problem, we may be able to help you out.
The behavior you're seeing suggests that the "T" isn't actually in the string.
Otherwise, I typically use code more like this:
var f2 = departure.split('T')[1];
(but only if I know there is actually a T in the datetime)

Related

Why is Net.Socket.Write() not sending the full string to my TCP client?

EDIT: Im desperate to get this thing done so I can move onto a new project, heres the source: https://github.com/eanlockwood/TalkmonClient
Everything else works fine. The server is well aware of the usernames associated with the clients and it sends information to them accordingly, but the weird thing is the string cuts off after the first variable. Here is the loop for a typical send message:
function SendMessage(msg, client)
{
const clientName = ClientNames.get(client);
let recieverMsg = `${clientName}: ${msg}`;
console.log(recieverMsg);
Clients.forEach(elm => {
if(elm != client)
{
elm.write(recieverMsg);
}
else {
elm.write("You: " + msg);
}
})
}
msg is the chunk.toString() in the socket.on('data') event, again, node picks up what this string means, it debugs fine but in the client (imagine the windows cmd) itll just print the username and go to the next line.
The loop for the client side is pretty simple too,
char buff[4090];
do
{
ZeroMemory(buff, 4090);
int messageRevieved = recv(sock, buff, 4090, 0);
if (messageRevieved > 0)
{
userInput->FreezeInput();
cout << buff << endl;
userInput->UnFreezeInput();
}
} while (0 == 0);
User input is handled in its own class on a seperate thread, again, working just fine.
I think it has to do with a misunderstanding of what socket.write and recv actually do or maybe I just dont understand javascript strings enough. Either way this problem is annoying because its the last step in creating my app
Ive done some extensive tests too, it really just doesnt like the concat strings. Itll print everything up until the first variable, meaning I could have socket.write("hehehehehehe " + variable1 + " kadjgkdgad"); and it would print hehehehehe [variable1 value] and just stop
Tl;dr: The server will write to the sockets up to the first variable in a concat'd string and then stop, its so weird.
EDIT: The dependencies used serverside are Net and dotnet if that makes a difference.
EDIT 2: I found another issue. After sending a few messages the client who sent the messages will stop printing the "you: " part and will only print the message, it will do this server side too but its weird because the receiving clients will still print out who the message is from.

SQLite error "No such column" when I can see that the column exists

The backstory here is that I'm working on a Discord bot. One of the requested functions is having it lob insults. I thought it would be fun to give users the ability to add insults via a SQLite 3 database (specifically, better-sqlite3), and in doing so, I also want to keep track of the most recent use of each insult (this is for future use in an "insultinfo" type command). I added a DATETIME column called "lastUsed". My insultadd command is able to write to this column when new insults are added. The issue is when I call the insult command, it's supposed to say the insult and then update the lastUsed field with the current date. Pasting the code below.
The problem is that I'm getting an error that says "SQLiteError: no such column:" and then it prints the date value even though I'm trying to update the lastUsed column and I can't figure out how to resolve this. The issue has to be in the db.prepare statement, I'm just not seeing what I need to do to fix it.
execute(msg, args) {
const SQLite = require("better-sqlite3");
const db = new SQLite('./userinputs.sqlite');
// Check if the table "userinputs" exists and has content from this guild.
const table = db.prepare(`SELECT count(*) FROM userinputs WHERE (guild = ${msg.guild.id} OR guild = 'Global') AND type = 'insult';`).get();
if (!table['count(*)']) {
return msg.channel.send("I don't have any insults yet");
}
var date = new Date();
const rawInsult = db.prepare(`SELECT * FROM userinputs WHERE type = 'insult' AND (guild = ${msg.guild.id} OR guild = 'Global') ORDER BY RANDOM() LIMIT 1;`).get();
const insult = rawInsult['content'];
const insultID = rawInsult['row'];
if (args[0]) {
var target = args[0];
} else {
var target = msg.author.username;
}
if (insult.includes('{}')) {
var finalInsult = insult.replace('{}', target);
} else {
var finalInsult = target + ' ' + insult;
}
msg.channel.send(finalInsult);
db.prepare(`UPDATE userinputs SET lastUsed = "${date}" WHERE row = ${insultID};`).run();
},
I think I got it. I ended up using date.toString() and it appears to have done the job. The error message I got after updating the db.prepare statement indicated it wasn't viewing that date variable as something it could work with, hence the .toString() workaround. I'll have to test this to see if that impacts my ability to sort on that column, since this is still all a pretty new to me, but at least the command itself is working and the database table is updating.
I'm open to more feedback though if anyone sees the probable folly in my ways here.
UPDATE: Upon further testing, setting date = Math.floor(new Date() / 1000) ended up working better in my case.

Apify web scraper task not stable. Getting different results between runs minutes apart

I'm building a very simple scraper to get the 'now playing' info from an online radio station I like to listen too.
It's stored in a simple p element on their site:
data html location
Now using the standard apify/web-scraper I run into a strange issue. The scraping sometimes works, but sometimes doesn't using this code:
async function pageFunction(context) {
const { request, log, jQuery } = context;
const $ = jQuery;
const nowPlaying = $('p.js-playing-now').text();
return {
nowPlaying
};
}
If the scraper works I get this result:
[{"nowPlaying": "Hangover Hotline - hosted by Lamebrane"}]
But if it doesn't I get this:
[{"nowPlaying": ""}]
And there is only a 5 minute difference between the two scrapes. The website doesn't change, the data is always presented in the same way. I tried checking all the boxes to circumvent security and different mixes of options (Use Chrome, Use Stealth, Ignore SSL errors, Ignore CORS and CSP) but that doesn't seem to fix it unfortunately.
Scraping instable
Any suggestions on how I can get this scraping task to constantly return the data I need?
It would be great if you can attach the URL, it will help me to find out the problem.
With the information you provided, I guess that the data you want to are loaded asynchronously. You can use context.waitFor() function.
async function pageFunction(context) {
const { request, log, jQuery } = context;
const $ = jQuery;
await context.waitFor(() => !!$('p.js-playing-now').text());
const nowPlaying = $('p.js-playing-now').text();
return {
nowPlaying
};
}
You can pass the function to wait, and I will wait until the result of the function will be true. You can check the doc.

Weird (caching) issue with Express/Node

I've built an angular/express/node app that runs in google cloud which currently uses a JSON file that serves as a data source for my application. For some reason, (and this only happens in the cloud) when saving data through an ajax call and writing it to the json file, everything seems to work fine. However, when refreshing the page, the server (sometimes!) sends me the version before the edit. I can't tell whether this is an Express-related, Node-related or even Angular-related problem, but what I know for sure is that I'm checking the JSON that comes in the response from the server, and it really is sometimes the modified version, sometimes not, so it most probably isn't angular cache-related.
The GET:
router.get('/concerts', function (request, response) {
delete require.cache[require.resolve('../database/data.json')];
var db = require('../database/data.json');
response.send(db.concerts);
});
The POST:
router.post('/concerts/save', function (request, response) {
delete require.cache[require.resolve('../database/data.json')];
var db = require('../database/data.json');
var concert = request.body;
console.log('Received concert id ' + concert.id + ' for saving.');
if (concert.id != 0) {
var indexOfItemToSave = db.concerts.map(function (e) {
return e.id;
}).indexOf(concert.id);
if (indexOfItemToSave == -1) {
console.log('Couldn\'t find concert with id ' + concert.id + 'in database!');
response.sendStatus(404);
return;
}
db.concerts[indexOfItemToSave] = concert;
}
else if (concert.id == 0) {
concert.id = db.concerts[db.concerts.length - 1].id + 1;
console.log('Concert id was 0, adding it with id ' + concert.id + '.');
db.concerts.push(concert);
}
console.log("Added stuff to temporary db");
var error = commit(db);
if (error)
response.send(error);
else
response.status(200).send(concert.id + '');
});
This probably doesn't say much, so if someone is interested in helping, you can see the issue live here. If you click on modify for the first concert and change the programme to something like asd and then save, everything looks fine. But if you try to refresh the page a few times (usually even up to 6-7 tries are needed) the old, unchanged programme is shown. Any clue or advice greatly appreciated, thanks.
To solve: Do not use local files to store data in cloud! This is what databases are for!
What was actually the problem?
The problem was caused by the fact that the App Engine had 2 VM instances running for my application. This caused the POST request to be sent to one instance, it did its job, saved the data by modifying its local JSON file, and returned a 200. However, after a few refreshes, the load balancing causes the GET to arrive at the other machine, which has its individual source code, including the initial, unmodified JSON. I am now using a MongoDB instance, and everything seems to be solved. Hopefully this discourages people who attempt to do the same thing I did.

javascript alert not working when API http request has json error (nothing found)

I'm using a thesaurus API,
http://thesaurus.altervista.org
to get synonyms to print to the page. In this demo version,
http://plnkr.co/edit/6pNYlXcgiwxHz00AY5CT?p=preview
it works when you type 'peace', otherwise, in console, if we follow the link, we see a GET error:
{"error":"the key test_only is restricted, please use your own key!"}
(EDIT: to clarify: Demo mode is not the issue. I want to make an alert.) For errors, I want the browser to alert "Oops, word not found. Please choose another word."
Here is the js code from the demo:
//function activated on user input
function myFunc(){
var userInput = document.getElementById('userInput');
var result = userInput.value;
var s = document.createElement("script");
//This demo works with the keyword 'peace' only. So searching for e.g. 'hat' will cause an error.
s.src = "http://thesaurus.altervista.org/service.php?word=" + result + "&language=en_US&output=json&key=test_only&callback=process"; // NOTE: replace test_only with your own KEY
document.getElementsByTagName("head")[0].appendChild(s);
window.process = function (result) {
//my attempt at throwing an error
if(result.error){alert("Oops, word not found. Please choose another word.");}
//normal processing..
output = "";
for (key in result.response) {
list = result.response[key].list;
output += list.synonyms+"<br>";
}
if (output)
document.getElementById("synonyms").innerHTML = output;
}
}
I did some research and found this answer (it's jQuery but mine's not but it might be relevant?):
https://stackoverflow.com/a/2568788
Any help much appreciated, thanks.
It's because you need to generate your own key. The key you are using is just a sample key.
Right there.
Then you'll change test_only is the URL by the generated key.
Anyhow, that perhaps means that the service is not free of use, so be careful and read the license if you plan to use it commercially.
You need to replace the test API key with your API key.
You can get your API key by going to http://thesaurus.altervista.org/mykey and signing up or logging in.
You even have a comment in your code telling you to do this:
s.src = "http://thesaurus.altervista.org/service.php?word=" + result + "&language=en_US&output=json&key=test_only&callback=process";
// NOTE: replace test_only with your own KEY
So if your API key 123456789, your URL will look like this:
s.src = "http://thesaurus.altervista.org/service.php?word=" + result + "&language=en_US&output=json&key=123456789&callback=process";

Categories

Resources