Actually I think there is an even better way to get the prices using this npm (you can open it to see better how it works):
https://github.com/jaggedsoft/node-binance-api than using the "coin "variable I am trying to use but I don't know how it could be possible, if you guys could help me to figure out with a better idea or the best way to pull prices with this package using discord it would be awesome, I've been already some days sticked to it :/
What I need:
To be able to replace "ticker.XRPBTC" (code below).
For example if I write ETH it should be changed from ticker.XRPBTC to ticker.ETHBTC
var coin = (message.content.toUpperCase()).slice(2) + "BTC";
binance.prices((error, ticker) => {
console.log("Price of " + coin + ":", ticker.XRPBTC);
});
for that I made the variable coin, I thought I could just write ticker.coin but it does not work...
I have tried this:
As an example:
ticker.XRPBTC - This code works, output: the actual price of the currency.
What I am trying:
var coin = XRPBTC
console.log(ticker.coin) - output: undefined
btw. I am writting console.log to test it in the console but I also have an error if I write:
if (msg.startsWith ("eth")) {
message.reply ("Price of " + coin + ":", ticker.TRXBTC);
}
an explanation of what ticker does:
The ticker has the function to get the last price of each currency, it can be for example ETHBTC, XRPBTC, TRXBTC etc. in this case eth, xrp and trx are the currencies. So in the ticker I just need to write it that way so that I can get the price for that pair.
As you can see in the code I sent you above, I am getting the text exactly how the ticker would "need it to look".
So if I write eth, the variable "coin" is transforming it into ETHBTC
Best!
I think you're looking for property access. You might want to check if the coin exists first, e.g.
var coin = message.content.toUpperCase().slice(2) + "BTC";
console.log(coin); // logs e.g. "ETHBTC"
binance.prices((error, ticker) => {
if (coin in ticker) {
var price = ticker[coin]; // <- property access
message.reply("Price of " + coin + ": " + price);
} else {
// handle error, e.g.
message.reply("Coin " + coin + " doesn't exist");
}
});
Related
I'm trying to make a notes command for specific users, but my Discord bot makes the notes any note that a user public has said. How do I fix this? I already know the problem with my code, but I don't know how to fix it.
if (command == "Note") {
const notes = db.fetch('userInfo');
while (!args[0]) return message.channel.send("Here are your notes: " + notes);
db.set('userInfo', args.join(' '));
message.channel.send((args.join(' ')) + (" successfully noted!"));
}
You have a row called userInfo, this row gets updated whenever someone executes the command. If you want it to link with a user, you're better of using the id of the user because everyone has a different ID. I suggest using something like:
const notes = db.fetch(`userInfo.${message.author.id}`)
while (!args[0]) return message.channel.send("Here are your notes: " + notes )
db.set('userInfo.${message.author.id}', args.join(' '))
message.channel.send(args.join(' ') + " successfully noted!")
a few days ago i made a code to mention users when they join my discord server, this is the code i currently have:
bot.on( "guildMemberAdd", member => {
let textChannel = member.guild.channels.find(channel => channel.id === '569582472812298240');
if (textChannel){
var messages = [
`Brace yourselves. <#${member.user.id}> just joined the server.`,
`Challenger approaching - <#${member.user.id}> has appeared`,
`Welcome <#${member.user.id}>. Leave your weapon by the door.`,
`Big <#${member.user.id}> showed up!`,
`<#${member.user.id}> just joined... or did they?`,
`Ready player <#${member.user.id}>`,
`<#${member.user.id}> hopped into the server. Kangaroo!!`,
`<#${member.user.id}> joined. You must construct additional pylons.`,
`Hello. Is it <#${member.user.id}> you're looking for?`,
`Where's <#${member.user.id}> in the server!`,
`It's dangerous to go alone, take <#${member.user.id}>`
]
textChannel.send({embed: {
color: 3447003,
description: messages[ Math.floor( Math.random() * 11 ) ],
timestamp: new Date(),
}
});
}
});
The problem? Sometimes i get the correct nickname of the person as you can see in this picture, but other times i get just numbers and i can't even click on that 'link'...
Correct way:
They are clickable and i can see their profile.
Incorrect way:
I can't click their id, nothing can be done with it.
Not sure why this happens randomly, any help would be extremely appreciated.
If someone joins the server and then leaves, and you have no other mutual servers with them and are not their friend, it'll just show their user id. This is a client side thing and there isn't really any real fix for mentions. You can however opt to just send their username instead of a mention.
You could try running toString on the member object, as it will automatically generate the right mention (as sometimes it can be prepended with <#!), but the likely reason it still won't work is because your Discord client did not cache the user that just joined.
It can be either because you're in a log channel, the server has too many members or the member left before your Discord client cached the user. You can either try to not use an embed, or (probably the best solution) provide the full username as well as the mention in the embed.
Try this:
bot.on('guildMemberAdd', member => {
var ran = randomRange(0,2);
var greeting;
switch (ran) {
case 0:
greeting = "Brace yourselves. " + member.user + " just joined the server.";
break;
case 1:
greeting = "Challenger approaching - " + member.user + " has appeared";
break;
case 2:
greeting = "Welcome " + member.user + ". Leave your weapon by the door.";
break;
// add more if you want (but dont forget to also change the values in line 2
}
member.guild.channels.get('CHANNEL ID HERE').send(greeting);
});
And add this function:
function randomRange(min, max) { // returns an int >= min and <= max
return Math.floor(Math.random() * (max - min + 1)) + min;
}
So what I'm trying to do is create a "cooldown" like system for my discord bot, I've tried using a database method, here which doesn't work for me.
I'm using the discord.js package.
Here is my code:
if (msg.content.startsWith("!point")) {
var usr = msg.content.split(" ").slice(1).join(" ");
if (!usr) {
bot.sendMessage(msg, "```Error: 1\n Reason: Please state a name.```");
return;
}
if (usr == msg.author.username) {
bot.sendMessage(msg, "```Error: 3\n Reason: You're unable to point yourself.```");
return;
}
if (!db["users"][usr]) {
db["users"][usr] = 0;
}
console.log(usr + " has " + db["users"][usr]);
db["users"][usr] += 1;
console.log(usr + " now has " + db["users"][usr]);
fs.writeFileSync('database.json', JSON.stringify(db));
bot.sendMessage(msg, usr + " has received 1 point");
}
Unless it's very important that the cooldown survives a crash, or the cool down is a very long duration I recomend creating an object with keys that are are either channel or user or server id's depending on what you want the rate limit to apply to. Then every time a command is run set that to the current time. Something like
rateLimitObject[msg.author.id] = "current time";
Then whenever someone runs a command just ensure that the current time is greater than the time in the object with that index by more than a certain amount.
If you are looking to just simply stop people from spamming the command something similar to what's used in pvpcraft here may be more ideal.
https://github.com/macdja38/pvpcraft/blob/master/middleware/rateLimits.js
I have two html datalists, and I get their input values to query a json file. I first search the keys of my json file which are college majors, their values are their courses. So once the object key equals the program, I return that element because I want to further query that element with the second input field which is a course number. This step is always successful at returning the correct program courses corresponding to the program input.
The second step is where things go bad. I want to now take that program element and look through all the names of the courses in that program. I concatenate the two input fields, program + " " + course. The program is a major like "CSE" or "I S" and the course is any 3 digit number like "143" or "310". Each object element in the program has a string name attribute like "CSE 143". This name attribute does not equal the program + " " + course even though they are both of type string and the same value WHEN I am looking at a program that has a space in it. For example, I want to find the course "I S 310". I successfully search for the program name that equals "I S". I iterate through the keys and find the correct element value using this operation Object.keys(jsondata[index]) == program. program is a variable containing the string "I S". As stated previously, this is successful, but if I iterate through the children of that objectkey value to find id, like programdata[index].children == program + " " + course, it doesnt work. If I instead hardcode the value, programdata[index].children == "I S 310", it works! This leads me to believe that the concatenation operation for these two variables changes the encoding of the string. According to console.log, the type of "I S 310" and program + " " + course are both Strings except they output a different encodeURIComponent().
Ill write what the output to the console is since im not reputable enough:
Step 1
function getProgramCourses(data, program) {
var programKeys = Object.keys(data);
for (var i = 0; i < programKeys.length; i++) {
if (Object.keys(data[i]) == program) {
return data[i][Object.keys(data[i])];
}
}
return objs
}
program = "CSE"
console.log(program)
console.log(encodeURIComponent(program));
Output:
CSE
CSE
program = "I S"
console.log(program)
console.log(encodeURIComponent(program));
Output:
I S
I%C2%A0S
Those unencoded hidden characters dont affect this first step of finding the courses offered by the "I S" program. Now when I want to find a specific course within the "I S" program like "I S 310":
Step 2
//data is object array of all courses in this program
function getCourse(data, program, course) {
pc = program + " " course;
for (var i = 0; i < data.length; i++) {
if (data[i].name == pc) {
return data[i];
}
}
}
"CSE" = program and "143" = course
pc = program + " " + course;
console.log(pc)
console.log(encodeURIComponent(pc));
Output:
CSE 142
CSE%20142
["I S" = program and "310" = course][2]
pc = program + " " + course;
console.log(pc)
console.log(encodeURIComponent(pc));
Output:
I S 310
I%C2%A0S%20310
This second step only works for programs that dont have spaces like "CSE" or "MATH". Doesnt work for "A A" or "I S". data[i].name is type String and so is pc.
Sorry about the lengthy post, I just wanted to be as descriptive as possible. Any help would be greatly appreciated.
Basically
Here is my problem:
console.log("A A 198")
console.log(encodeURIComponent("A A 198"))
console.log(program + " " + course)
console.log(encodeURIComponent(program + " " + course))
Output:
A A 198
A%20A%20198
A A 198
A%C2%A0A%20198
not equal
Your program variable contains a character which is like a space but isn't a space. Make sure it isn't an encoding issue, else you can fix this with this simple code.
encodeURIComponent(program.replace(/\u00a0/g, ' ') + ' ' + course)
I was interested in writing a twitter bot to help out some friends at a local ski resort. I found this tutorial from Amit Agarwal which gave me enough to get started (it did take me more than 5 minutes since I did a lot of modifying). I host the script on google docs.
FIRST I think this is javascript (my understanding is that google apps script uses javascript...) and when I have had problems with the code so far, google searches for javascript-such-and-such have been helpful, but if this is not actually javascript, please let me know so I can update the tag accordingly!
I have no prior experience with javascript, so I am pretty happy that it's actually working. But I want to see if I'm doing this right.
The start function initiates the trigger, which kicks off the fetchTweets() function every interval (30 minutes). In order to avoid duplicates (the first errors I encountered) & potentially being flagged as spam, I needed a way to ensure that I was not posting the same tweets over and over again. Within the start() function, the initial since_id value is assigned:
ScriptProperties.setProperty("SINCE_TWITTER_ID", "404251049889759234");
Within the fetchTweet() function, I think I am updating this property with the statement:
ScriptProperties.setProperty("SINCE_TWITTER_ID", lastID + '\n');
Is this a good way to do this? Or is there a better/more reliable way? And if so, how can I be sure it's updating the property? (I can check the log file and it seems to be doing it, so I probably just need to create a permanent text file for the logger).
Any help is greatly appreciated!!
/** A S I M P L E T W I T T E R B O T **/
/** ======================================= **/
/** Written by Amit Agarwal #labnol on 03/08/2013 **/
/** Modified by David Zemens #agnarchy on 11/21/2013 **/
/** Tutorial link: http://www.labnol.org/?p=27902 **/
/** Live demo at http://twitter.com/DearAssistant **/
/** Last updated on 09/07/2013 - Twitter API Fix **/
function start() {
Logger.log("start!" + '\n')
// REPLACE THESE DUMMY VALUES
// https://script.google.com/macros/d/18DGYaa-jbaAK9rEv0HZ2cMcWjFGgkvVcvr6TfksMNbbu2Brk3gZeZ46R/edit
var TWITTER_CONSUMER_KEY = "___REDACTED___";
var TWITTER_CONSUMER_SECRET = "___REDACTED___";
var TWITTER_HANDLE = "___REDACTED___";
var SEARCH_QUERY = "___REDACTED___" + TWITTER_HANDLE;
// Store variables
ScriptProperties.setProperty("TWITTER_CONSUMER_KEY", TWITTER_CONSUMER_KEY);
ScriptProperties.setProperty("TWITTER_CONSUMER_SECRET", TWITTER_CONSUMER_SECRET);
ScriptProperties.setProperty("TWITTER_HANDLE", TWITTER_HANDLE);
ScriptProperties.setProperty("SEARCH_QUERY", SEARCH_QUERY);
ScriptProperties.setProperty("SINCE_TWITTER_ID", "404251049889759234");
// Delete exiting triggers, if any
var triggers = ScriptApp.getScriptTriggers();
for(var i=0; i < triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i]);
}
// Setup trigger to read Tweets every 2 hours
ScriptApp.newTrigger("fetchTweets")
.timeBased()
.everyMinutes(30)
//.everyHours(2)
.create();
}
function oAuth() {
//Authentication
var oauthConfig = UrlFetchApp.addOAuthService("twitter");
oauthConfig.setAccessTokenUrl("https://api.twitter.com/oauth/access_token");
oauthConfig.setRequestTokenUrl("https://api.twitter.com/oauth/request_token");
oauthConfig.setAuthorizationUrl("https://api.twitter.com/oauth/authorize");
oauthConfig.setConsumerKey(ScriptProperties.getProperty("TWITTER_CONSUMER_KEY"));
oauthConfig.setConsumerSecret(ScriptProperties.getProperty("TWITTER_CONSUMER_SECRET"));
}
function fetchTweets() {
oAuth();
// I put this line in to monitor whether the property is getting "stored" so as to avoid
// reading in duplicate tweets.
Logger.log("Getting tweets since " + ScriptProperties.getProperty("SINCE_TWITTER_ID"))
var twitter_handle = ScriptProperties.getProperty("TWITTER_HANDLE");
var search_query = ScriptProperties.getProperty("SEARCH_QUERY")
Logger.log("searching tweets to " + search_query + '\n');
// form the base URL
// restrict to a certain radius ---:
//var search = "https://api.twitter.com/1.1/search/tweets.json?count=5&geocode=42.827934,-83.564306,75mi&include_entities=false&result_type=recent&q=";
// unrestricted radius:
var search = "https://api.twitter.com/1.1/search/tweets.json?count=5&include_entities=false&result_type=recent&q=";
search = search + encodeString(search_query) + "&since_id=" + ScriptProperties.getProperty("SINCE_TWITTER_ID");
var options =
{
"method": "get",
"oAuthServiceName":"twitter",
"oAuthUseToken":"always"
};
try {
var result = UrlFetchApp.fetch(search, options);
var lastID = ScriptProperties.getProperty("SINCE_TWITTER_ID");
if (result.getResponseCode() === 200) {
var data = Utilities.jsonParse(result.getContentText());
if (data) {
var tweets = data.statuses;
//Logger.log(data.statuses);
for (var i=tweets.length-1; i>=0; i--) {
// Make sure this is a NEW tweet
if (tweets[i].id > ScriptProperties.getProperty("SINCE_TWITTER_ID")) {
lastID = (tweets[i].id_str);
var answer = tweets[i].text.replace(new RegExp("\#" + twitter_handle, "ig"), "").replace(twitter_handle, "");
// I find this TRY block may be necessary since a failure to send one of the tweets
// may abort the rest of the loop.
try {
Logger.log("found >> " + tweets[i].text)
Logger.log("converted >> " + answer + '\n');
sendTweet(tweets[i].user.screen_name, tweets[i].id_str, answer.substring(0,140));
// Update the script property to avoid duplicates.
ScriptProperties.setProperty("SINCE_TWITTER_ID", lastID);
Logger.log("sent to #" + tweets[i].user.screen_name + '\n');
} catch (e) {
Logger.log(e.toString() + '\n');
}
}
}
}
}
} catch (e) {
Logger.log(e.toString() + '\n');
}
Logger.log("Last used tweet.id: " + lastID + + "\n")
}
function sendTweet(user, reply_id, tweet) {
var options =
{
"method": "POST",
"oAuthServiceName":"twitter",
"oAuthUseToken":"always"
};
var status = "https://api.twitter.com/1.1/statuses/update.json";
status = status + "?status=" + encodeString("RT #" + user + " " + tweet + " - Thanks\!");
status = status + "&in_reply_to_status_id=" + reply_id;
try {
var result = UrlFetchApp.fetch(status, options);
Logger.log("JSON result = " + result.getContentText() + '\n');
}
catch (e) {
Logger.log(e.toString() + '\n');
}
}
// Thank you +Martin Hawksey - you are awesome
function encodeString (q) {
// Update: 09/06/2013
// Google Apps Script is having issues storing oAuth tokens with the Twitter API 1.1 due to some encoding issues.
// Henc this workaround to remove all the problematic characters from the status message.
var str = q.replace(/\(/g,'{').replace(/\)/g,'}').replace(/\[/g,'{').replace(/\]/g,'}').replace(/\!/g, '|').replace(/\*/g, 'x').replace(/\'/g, '');
return encodeURIComponent(str);
// var str = encodeURIComponent(q);
// str = str.replace(/!/g,'%21');
// str = str.replace(/\*/g,'%2A');
// str = str.replace(/\(/g,'%28');
// str = str.replace(/\)/g,'%29');
// str = str.replace(/'/g,'%27');
// return str;
}
When you use ScriptProperties.setProperty("KEY", "VALUE");, internally Script Properties will overwrite a duplicate key (i.e., if an old Property has the same key, your new one will replace it). So in your case, since you are using the same identifier for the key (SINCE_TWITTER_ID), it will replace any previous Script Property that is that key.
Furthermore, you can view Script Properties via File -> Project properties -> Project properties (tab). Imo Google didn't name that very well. User properties as specific to Google users. Script properties as specific to the Script Project you are working under.
Also, it probably isn't a good idea to include \n in your value when you set the property. That will lead to all sorts of bugs down the road, because you'll have to compare with something like the following:
var valToCompare = "My value\n";
instead of:
var valToCompare = "My value";
because the value in SINCE_TWITTER_ID will actually be "some value\n" after you call your fetchTweet() function.
Of course, one seems more logical I think, unless you really need the line breaks (in which case you should be using them somewhere else, for this application).
Its ok like that thou I dont know why you are adding \n at fhe end. Might confuse other code. You can see script properties in the script's file menu+ properties