Why can't my translation script handle cyrillic or chinese letters? - node.js

I'm trying to build a really simple translating script for people who want to say something in their native language and get it translated into english. It works surprisingly well, but it cannot handle cyrillic (or chinese for example) letters at all.
if(message.content.toLowerCase().startsWith("+t ")) {
var args = message.content.substring(3).split(" ");
if(!args[0]) {
message.channel.send("What do you want to translate?");
return;
}
let gurl = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=english&dt=t&q=" + args.join("%20");
request(gurl, function(error, response, body) {
try {
let translated = body.match(/^\[\[\[".+?",/)[0];
translated = translated.substring(4, translated.length - 2);
message.delete().catch(O_o=>{});
message.channel.send("**"+message.author.username+"** (via translator): " + translated);
} catch(err) {
message.channel.send("Failed: "+err);
}
});
}
err = TypeError: Cannot read property 'match' of undefined if I try to translate them. Do I need to encode them somehow compatible to latin first or how should I approach the problem?

Related

if object is invalid json format - forward contents forward contents anyway - NODEJS

I am currently forwarding cloudwatch alarms to slack using a nodejs lambda function I found on github, however, when it receives a custom alert from one of our customers datacenters, the string is not in a JSON format, so it will not print the alert.
I am looking at rewriting the handleCatchAll() function to handle the string and just forward it to slack in its current format, but am having issues identifying the object.
Below is the code i am trying to edit, I need to write an if statement that will identify the object, say "if JSON.stringify fails, then render the message without JSON.stringify and input its value into 'description'"
var description = ""
if ()
{
else if ()
{
for(key in message) {
var renderedMessage = typeof message[key] === 'object'
? JSON.stringify(message[key])
: message[key]
description = description + "\n" + key + ": " + renderedMessage
}
}
}
You can use this script to convert text input into json if the text is a valid JSON object, or else keep the original text.
const isJSON = str => {
try {
return (JSON.parse(str) && !!str);
} catch (e) {
return false;
}
}
const regulizeRequestBody = body => isJSON(body) ? JSON.parse(body) : body;

tmi.js message with input/argument?

Im am working on a twitch-bot using the tmi.js-npm and got a question about that.
I want to make a command like - "!giveaway" with an input, which could be anything. eg. "!giveaway pg". Then it should return "!pg". So the keyword "!giveaway" should be fixed, but the part after the blank, could be anything that is typed in.
My script looks like this:
client.on("chat", function (channel, user, message, self) {
if (message === "!Giveaway" + " " + "input"){
if(user["display-name"] === "username"){
client.say("channel", "!" + "input");
} else {
client.say("channel", "No permissions");
}
};
});
Thanks :)
Something like this is most commonly used, adding more checks is advised, but depends on your needs.
Checking the incoming message to see if it starts with a specific command, like so:
message.startsWith("!giveaway")
and with other logic
if (message.startsWith("!giveaway")) {
var input = message.split(' ')[1];
if (input.count < 2) return;
if (user["display-name"] === "username") {
client.say("channel", "!" + input);
} else {
client.say("channel", "No permissions");
}
}

code explanation nodejs expressjs mongoose

i feel a bit embarrassed, can you please kindly explain parts of the code?
For example, I have no idea, what is this part? where can I read more about it?
function parsePostStory(data) {
return {
name : data.name
}
}
What is req.body? Is it json req body?
Why do we declare empty array and why do we return it? Just for the clarity?
Is Story.create just a mongoose method?
The rest of the code is here:
router.post('/stories', function(req, res) {
var validation = validatePostStory(req.body);
if(validation.length > 0) {
return res.badRequestError(validation);
}
var story = parsePostStory(req.body);
Story.create(story, function(err, story) {
if(err) {
console.log(err.message);
return res.internalServerError();
} res.send(story);
});
});
function validatePostStory(data) {
var array = [];
if (!data.name || typeof data.name !== 'String') {
return array.push('name');
}
return array;
}
function parsePostStory(data) {
return {
name : data.name
}
}
Sorry once more for that kind of a question and thanks a ton.
I'm assuming you know how the request-response cycle works with HTTP requests and the client-server interactions with it. If not, Wikipedia Request-Response and Client-Server (Two link limit, otherwise I would have posted them as links)
A request sends a lot of information to the server. If you console.log the request in NodeJS, you will see that it contains a lot of information that isn't entirely relevant to what you need.
You're using Express as your web framework. In this case, req.body is the information that you are sending to the server from the client. Using req.body will make sure that you're not using the extra information passed in to the server from the client. Req.body is your code that you want. (Note: Req.body isn't natively supported by Express v4, you'll have to use something like body-parser) See Express docs for more details
Now, let's break up this code a bit. You essentially have 3 separate functions. Let's take a look at validatePostStory.
function validatePostStory(data) {
var array = [];
if (!data.name || typeof data.name !== 'String') {
return array.push('name');
}
return array;
}
This function is a validation function. It takes one argument - an object and returns an array. Effectively, what this is doing is checking if the name is a string or not - if not, return an array that has a length of 1. The following conditional checks length and returns a 400 if greater than 0
if(validation.length > 0) {
return res.badRequestError(validation);
}
I'm not entirely sure why this needs to be a separate function. Looks like you can probably just do this instead.
if (!req.body.name || typeof req.body.name !== 'String') {
return res.badRequestError(validation);
}
The following function function essentially converts the data so that mongodb/mongoose can store it in the proper format
function parsePostStory(data) {
return {
name : data.name
}
}
It's the same as saying:
var story = {name: req.body.name}
I would assume Story.create is a custom mongoose method yes.

Parse.com set class default attributes

I have been working with Parse Cloud Code, and I have not achieved setting default values for my classes. Right now I am doing this:
Parse.Cloud.beforeSave('MyClass',function(request, response){
//The description should only have 200 characters
if(request.object.get('description')){
var des = request.object.get('description');
if(des.length>200){
request.object.set("description", des.substring(0, 197) + "...");
}
}
//let's make a default value
if(typeof request.object.get('active') === 'undefined'){
request.object.set('active',false);
}
response.success();
});
When I upload this function to the Cloud Code, and try to create a new object from the dashboard it wont have the default value active = false.
I don't know what's going on. Has somebody achieved this before?
My code is very similar to the one in the Parse docs. They say this could be done like this:
Parse.Cloud.beforeSave("Review", function(request, response) {
var comment = request.object.get("comment");
if (comment.length > 140) {
// Truncate and add a ...
request.object.set("comment", comment.substring(0, 137) + "...");
}
response.success();
});
However, for me it doesn't want to work.
Wohoo! I did it!
Nowhere in the documentation is said that if you want to do so, you must return the object you edited in the response.success().
Solution:
Parse.Cloud.beforeSave('MyClass',function(request, response){
//The description should only have 200 characters
if(request.object.get('description')){
var des = request.object.get('description');
if(des.length>200){
request.object.set("description", des.substring(0, 197) + "...");
}
}
//let's make a default value
if(typeof request.object.get('active') === 'undefined'){
request.object.set('active',false);
}
response.success(request.object); //this is the line that changes
});

Using Q to create an async user input sequence

I am toying with Q and promptly and I am trying to ask, in a sequence, the user to input some stuff. For example :
What is your name? Bob
What is your age? 40
Hello Bob (40)!
(yes! it's a simple "Hello world!" program.)
And here is the code I am trying, directly from Q's github project page :
Q.fcall(promptly.prompt, "What is your name? ")
.then(promptly.prompt, "What is your age? ")
.done(function(name, age) {
console.log("Hello " + name + " (" + age + ")");
});
});
But it is not working as expected (maybe I'm reading wrong?). Whatever I try, it seems that promptly.prompt is listening to keystroke in parallel, and the .done function is called right away, resulting into a
/path/to/node_modules/promptly/index.js:80
fn(null, data);
^
TypeError: undefined is not a function
at /path/to/node_modules/promptly/index.js:80:9
...
once I hit Enter. Any idea why this is doing so and how I can accomplish what I'm trying to do?
** Edit **
Basically, what my end goal would be to create a reusable function invoked like so :
promptAll({
'name': "What is your name? ",
'age': "What is your age? "
}).done(function(input) {
console.log(input); // ex: { name: "Bob", age: 40 }
});
** Update **
Here's my working solution, I had to use nfcall as suggested by WiredPraine :
function multiPrompt(args) {
function _next() {
if (keys.length) {
var key = keys.pop();
Q.nfcall(promptly.prompt, args[key]).done(function(value) {
result[key] = value;
_next();
});
} else {
def.resolve(result);
}
};
var def = Q.defer();
var keys = _.keys(args).reverse();
var result = {};
_next();
return def.promise;
};
(Note : I am using Underscore, but the same can be achieved with a standard object iterator.)
Below are two approaches.
First, you'd need to use nfcall so that Q uses the NodeJS conventions for callbacks.
But, as the functions aren't promises, you'll need to handle the chaining and synchronous behavior slightly differently.
In the first example, start1, the code creates an instance of defer and returns it as the promise. When the prompt function returns, it resolves the deferred object instance and passes the value of the function (ideally the prompt). It should also handle errors, etc. in "real" code.
In both examples, I've added a function to grab the result of the the promise resolving. It's not passed as parameters to the last done instance. The function passed to done will execute as soon as the first promise is resolved (after the prompt has returned in this case).
var promptly = require('promptly');
var Q = require('q');
// make a simple deferred/promise out of the prompt function
var prompter = function(text) {
var deferred = Q.defer();
promptly.prompt(text, function(err, value) {
deferred.resolve(value);
});
return deferred.promise;
};
// this option just uses the promise option to prompt for name.
function start1() {
prompter("What is your name?").then(function(name) {
prompter("Your age?").then(function(age) {
console.log("Hello " + name + " (" + age + ")");
});
});
}
// this one uses the nfcall funcitonality to directly call the
// promptly.prompt function (and waits for a callback).
function start2() {
Q.nfcall(promptly.prompt, "What is your name? ")
.then(function(name) {
Q.nfcall(promptly.prompt, "What is your age? ")
.done(function(age) {
console.log("Hello " + name + " (" + age + ")");
});
});
}
//start1();
I feel like the answers here can be added to for anyone seeking alternatives to solving the general problem of getting command line user input from node.
Firstly, I personally feel there is merit to moving towards the ES6 Promises API. Although not natively available yet in Node, there is a great polyfill: https://github.com/jakearchibald/es6-promise.
Secondly, I have come to like an alternative user prompting module: https://github.com/flatiron/prompt
Now assuming there exist methods 'addUserToDb', 'printUser' and 'printError' that in turn return promises, the following example is possible:
var prompt = require('node-prompt');
var Promise = require('es6-promise').Promise;
var promptUser = function(schema) {
return new Promise(resolve, reject) {
prompt.get(schema, function(err, result) {
if (err) {
reject(err);
} else {
resolve(result);
}
});
};
};
promptUser(["name", "password"])
.then(addUserToDb)
.then(printUser)
.catch(printError)
I've written many 'scripts' now using this method and have found it very nice to work with and easy to maintain / adapt.

Resources