Pushing Elements to a JSON Array with Braces - javascript

I am having a hard time trying to push elements to a JSON file located in an external location; here's a backstory on what I am trying to achieve:
I am programming a private Discord bot and am currently working on the message-system portion of it. The whole idea is that a user's message is deleted if they aren't fully authorized onto the server; that user's message and UserID will be logged into the JSON file . The thing is, I can only log the message if a UserID is manually added to the array (using the push function, I can add the message). But, if I try to push a UserID to the file array, it acts as if the push function does not exist for this; I think the JSON is nested as well. I would appreciate any help I can get, thanks!
JSON
{"users":[{}]}
I want to put the UserID within the braces inside the brackets
Code to push to the JSON
function removeMessage(content, authorid) {
if (!messagedata.users[0][authorid]) {
messagedata.users[0].push(authorid);
}
}
Current I'm Getting:
TypeError: messagedata.users[0].push is not a function
Expected Output
{"users":[{"287423028147781654":["Hi"]}]}
The numerical value is the UserID, while 'Hi' is clearly the message

users[0] is an object, not an array (and hence has no push method). It appears you actually want to add a key to the object, so try this instead:
messagedata.users[0][authorid] = ["Hi"];

Related

How do I get a result from this specific API request?

I am currently trying to make a command in my discord bot that will track your stats in Rainbow six Siege. I am using an API for this, but I can't get any results out of my API request. The API gives a player ID between "players" and "profile", but I have no idea how to get around it. I also tried to get the response via an array, but that also gave no results. The thing I want to achieve is getting the player name for example, but I don't know how to get a value out of there. I thought r.body.players.profile.p_name, but that doesn't work because the API gives a player ID in between it. Maybe that someone knows how to work around it?
The result of r.body
The code I want to use to simply get the player name, but "profile" will be undefined
This is what the API responds when just pasting the link in my browser
You can use
Object.entries(...)
Object.entries requires an object to send and
it returns new array with key and value.
For eg:
let data={
"4cc06f42-86f6-11ea-bc55-0242ac130003": {
name: "Stack Overflow",
type: "website"
}
}
let newArr=Object.entries(data);
/*["4cc06f42-86f6-11ea-bc55-0242ac130003",{name:
"Stack Overflow",
type: "website"}]*/
You can access the key by:
let key=newArr.map(value=>value[0])
// ["4cc06f42-86f6-11ea-bc55-0242ac130003"]
You can also use array destructing
let key=newArr.map(([key,value])=>key)
// ["4cc06f42-86f6-11ea-bc55-0242ac130003"]

Save data from GET request as variable

I've got a simple axios GET request that is working with Azure directline 3.0. The GET request pulls back data and shows it in the console (as seen in the picture).
The data I want to save into a variable is the conversationId. I then want to use this variable with Axios Post in another JS file to post as part of the link e.g. let URL = "https://directline.botframework.com/v3/directline/conversations/"+convID"/activities". With convID being the variable I wish to create. Right now I am manually changing the convID with the new conversation ID, but I want to create a variable so I can place it in the post javascript file so it is automatic.enter image description here
There are various ways you can solve this problem. Easiest one being, exposing the data on a shared object window.convID = convID and then accessing it wherever required.
You could also look to make singleton objects, which can be instantiated only once and hence will share it's variables across the lifespan of the application.
axios.get(/* URL */).then(res => {
window.convID = res.data.conversationId;
});
You can save that variable value in LocalStorage. Something like this:
let routeToYourApi = '/api/conversations'; // or something like this...
axios.get(routeToYourApi).then((response) => {
let conversationId = response.data.conversationId; // not sure if data object from your image is directly nested inside response that you get from server, but you get the idea...
window.localStorage.setItem("convId", conversationId);
}) // here you can fetch your conversation id
Than you can access it anywhere in your app:
let conversationId = window.localStorage.getItem("convId");
... and eventually remove it from local storage:
window.localStorage.removeItem("convId")
Hope this will help you!

JavaScript (Discord) Is there a way for my bot to store values and then repeat?

I have my current Discord Bot project using JavaScript however i cannot find a way to store the value itself when done through a command such as !setname ___ hoping for a response of that being repeated back when I use !myname.
I know how to do it by storing it temporarily through:
bot.on('message', function (user, userID, channelID, message, evt) {
if(message == "!myname") {
bot.sendMessage({
to: channelID,
message: 'Your name is ' + user.username;
});
}
}
However i cant figure out how to do it through the ability to call for it whenever you want rather than getting an immediate response. For example setting my name now but being able to have it output when i use the command instead of having command that sets the value then outputs it in an immediate string
Would recommend a simple key-value dictionary style in the current instance.
(Though you could store it to a text-file or database later if you prefer the data to be persistent across different sessions.)
Instance based:
Based on this post on stackoverflow...
You can create a global dictionary at the top var usernameChangeDict = {};
Whenever the user invokes !setname, just do:
usernameChangeDict[user.id] = Their_new_name_here
Fetch it back using usernameChangeDict[user.id], should return null or empty if they did not set their name before.
Persistent data:
Could either store it in a text file on your local computer, or do a database as Zooly mentioned.(Though personally, a database would be an overkill if your bot is not going to be used by a wide range of people.)
Text file
Read from this post, it contains details on how to write onto a text file.
This post talks about reading from a text file.
I would recommend storing it in a JSON format to make your life easier, since JSON.parse exists.
Most likely you would end up storing in a format like this:
{ "23125167744": "someone", "USER_ID": "username" }
Access it by parsedJson["USER_ID"].
SQLite
This tutorial would probably explain how to set your SQLite for javascript better than I do.
Once its all setup, just store the userID and username, you can just do:
SELECT username FROM yourTable WHERE userID = ?;
and
INSERT INTO yourTable (username, userID) VALUES (?, ?);
For inserting and selecting into database respectively.

Why is node.js variable persisting

I'm making a temporary fake API and am trying to set up a simple request response script in node using express.js to achieve this. It's very strraightforward, A request comes in, is validated and, if valid, is merged with a .json template file and the result returned, thus giving the impression the user was successfully created.
app.post('/agent/user', function(req, res){
var responseTemplate = new jsonRequired('post_user');
var errorTemplate = new jsonRequired('post_user_error');
var payload = req.body;
var responseData;
var hasErrors = false;
console.log('Creating new user');
//Recursive Merge from http://stackoverflow.com/a/383245/284695
responseData = new mergeRecursive(responseTemplate,payload);
if(!payload.username){
hasErrors = true;
errorTemplate.errors.username.push('A username is required.');
}
if (hasErrors){
res.send(errorTemplate,422);
}else{
res.send(responseData,200);
}
});
The problem I'm having is that data is persisting between calls. So if I define a username and name[first] in 1 request and just a username in the 2nd one, both requests come back with the name[first] property.
I have a feeling it's something to do with js closures. Unfortunately, every tutorial I find seems to be about making closures, not avoiding them.
It should work like this:
The client POST's username=user1&name[first]=joe&name[last]=bloggs
The Server loads a json file containing a prepopulated user object: e.g.
{"username":"demo","name":{"first":"John","last":"Doe"}...}
mergeRecursive() merges the payload from the POST request over the template object and returns the new object as the POST response text.
The problem is that with every new request, the server is using the result of step 3 in step 2 instead of reloading the .json file.
That mergeRecursive function has the same caveat as jQuery.extend: it modifies the first object sent into it. In fact, you don't even need to use its return value.
You didn't show the code of jsonRequired function (it's not even clear why you've used new when invoking it), but it looks like this function doesn't create a new object each time it's called, instead fetching this object from some outer repository. Obviously, mergeRecursive modifications for it won't be lost after that function ends.
The solution is using your data object for merging. Like this:
var responseData = {};
...
mergeRecursive(responseData, responseTemplate);
mergeRecursive(responseData, payload);
Merging two objects will make this for you.
If your responseTemplate has parameter, which actual request did not have, then you will end up having it there.
Check definition of word merge ;)
While this doesn't resolve the issue I had, I have found a workaround using the cloneextend package available via npm:
$ npm install cloneextend
This allows me to use the following js:
var ce = require('cloneextend');
...
ce.extend(responseData, responseTemplate);
ce.extend(responseData, payload);

How do I get the same format for a javascript array and django set on the backend?

I have code that, when a user is logged in, selects recipes that apply to him based on the ingredients (items) he has previously identified identified as possessions.
This code gets the id's of the items the user already has:
if request.user.is_authenticated():
user_items = [possession.item for possession in request.user.possession_set.all()]
user_items_ids = [item.id for item in user_items]
uids = set(user_items_ids)
The following code, which already existed, is where I run into problems...
recipes = [(recipe, len(set([item.id for item in recipe.items.all()]) & uids), recipe.votes) for recipe in recipes]
I created another part of the site that allows people who have not yet signed up to just pick a few ingredients. I do this with some jQuery on the front end, then send the results to the backend:
var ingredient_set = [];
$('.temp_ingredient').each(function(index){
ingredient_set[index] = $(this).attr('id').substr(4);
});
$.get('/recipes/discover', { 'ingredients': ingredient_set },
function(){
alert("Success");
});
The problem is when I receive them on the Django side, with this code:
uids = request.GET['ingredients']
I get the following error:
unsupported operand type(s) for &: 'set' and 'unicode'
Basically, I know they aren't in the same format, but I don't know how to get them to be compatible.
You are sending a JavaScript array in the query string of your GET request. Therefore you should use request.GET.getlist. Just using request.GET[key] gives you the last value for that key.
>> request.GET['foo[]']
u'5'
>> request.GET.getlist('foo[]')
[u'1', u'2', u'4', u'5']
Note that the values are unicode, but you probably need them as integers, so be sure to convert them.
uids = request.GET.getlist('foo[]')
uids = set([int(x) for x in uids])
I'm not sure why my key is actually foo[] and not just foo, but as you get no KeyError, request.GET.getlist('ingredients') should work.

Categories