How to Access Nested Data in Object Maps / Collections - javascript

Say I have a collection that gets automatically returned in my app when I call a function, and it turns out something like this:
Collection {
'1234567890' => Message {
channel: TextChannel {
type: 'text',
id: '362557066864230402'
},
type: "DEFAULT",
content: "test"
}
}
I'm unsure about the '1234567890' => Message part. I understand that it's ES6, but I don't know how to call any of the nested data inside of it, such as content: "test".
To get to that (assuming the collection is using the variable collection, I've tried:
let data = collection["123567890"].content;
let data2 = collection[0].content; //I know that's for arrays, but I thought it would be similar
Both output 'null' or undefined, with the error
TypeError: Cannot read property 'content' of undefined
So I understand that I cannot get the initial collection object.
One last thing: That number 1234567890 is randomly generated each time the function is called, so I cannot hardcode anything easily.
Pastebin to the actual collection example.
For some reason, it stops printing after that line (possibly too many characters?)
EDIT: My code:
msg.channel.awaitMessages(msg => msg.author==user, { time: 10000, max: 1, errors: ['time'] })
.then((collected) => {
let channel = collected[0];
console.log(collected);
console.log(JSON.stringify(collected));
if(channel=="cancel") {
msg.channel.send("cancel");
return;
}
})
.catch(() => {
// ect ect
});
Sorry that there isn't much clarification, this is really stumping me.

Related

Show length of data array in VueJS after getting the data from API

I'm using Vue JS to get some data from an API. I want to get the length of this array and log to console via a method.
But it always logs the value of "0" instead of the real length.
I can access the data in the html without any problem and show the length ( {{ termine.length }} ).
But I want to do it using the method "logToConsole".
It seems to be a problem to access the data (which seems to be undefined in the moment of function call).
I fetch the data on "created", and output the length in "mounted", so it should be available (?).
Do you have any idea why I cannot access the data of the array in my "mounted" function, even after getting the data in "created"?
new Vue ({
el: "#calendar",
data: {
termine: [],
},
},
created() {
fetch("https://www.myurl.com/data/?json&function=GetEvents")
.then(response => response.json())
.then((data) => {
this.termine = data;
})
},
mounted() {
this.logToConsole();
},
methods: {
logToConsole: function () {
console.log(this.termine.length);
},
},
})
Of course, created hook is triggered before mounted.
But you know, you are setting termine property using API response and it is happen with async.
If you simple set termine property with simple statement like this.termine = ['a', 'b'], it will logs 2.
If you want log the data after getting the value using API, you could use watch.
like:
watch: {
termine(val) {
console.log(val)
}
}

Extracting values from multiple scope inside an array

I'm building a twitter bot that takes input of someone that DM's my account, and then will output the received DM's into tweet. I'm using twit package from npm. The question is, how do you extract the id's from the output, and then use the id's in another function in order to post the tweet, using? (note that I'm currently using console.log as the tweet for now).
Input command to check the direct messages
var listMsg = T.get('direct_messages/events/list', {
count: '50'
}, function(data, response) {
console.log(response)
Output in terminal (the multiple scope inside the events array)
{
events: [
{
type: 'message_create',
id: '1275746339314216965', //take this
created_timestamp: '1592996604170',
message_create: [Object]
},
{
type: 'message_create',
id: '1274664227584671750', //and this
created_timestamp: '1592738608629',
message_create: [Object]
}
]
}
Getting the content of a direct message
var getMsg = T.get('direct_messages/events/show', {
id:'1274664227584671750' //put it to this
}, function(data, response) {
//console.log(response)
let dm = response.event.message_create.message_data
console.log(dm) //and print the message here
The content of the direct message
{
text: 'Abcd',
entities: { hashtags: [], symbols: [], user_mentions: [], urls: [] }
}
I want to get the id's as a let just like in the third code block.
You can simply use the map array function to transform the object like this
events.map( function(e) { return e.id}) or you can use es6 syntax events.map(e=> e.id)
both would return an array like this
["1275746339314216965", "1274664227584671750"]
These could be joined into into a string like so
events.map(e=> e.id).join(",")
returning
"1275746339314216965,1274664227584671750"
map() is a great function try playing around with map reduce and filter to really improve your programming. There's a great article on them here https://medium.com/poka-techblog/simplify-your-javascript-use-map-reduce-and-filter-bd02c593cc2d
Of course you could do also use a good old fashioned for loop, but think that would be a bit verbose and unnecessary (the software equivalent of making your own hammer)
e.g.
var ids = []
for(var event of events) {
ids.push(event.id)
}

mach beginning javascript with Array

Good afternoon, I am trying to make a method that tells me the number of elements an Array has that starts with "RT:"
For this I have developed the following code:
public getRowsRTs(idProyecto){
this.twitterService.getTargets().subscribe((data) => {
this.Twitter = data;
});
let countRT = this.Twitter.filter( tweet => tweet.message.startsWith("RT:")).length;
return countRT;
}
}
Here, data returns all the Documents that Mongo extracts, and puts them in the Twitter Array that I have defined at the beginning of the component. Within this Array each element has different attributes, such as _id, message, date ... I want you to tell me how many of those documents, the message value, begins with RT: and to return it to me, this code , it does not give me any problem, but it does not give me absolutely nothing, I do not know if someone could help me.
If the array is filled with strings, this should work:
let regixForRTStart = /^RT:/;
startArray = ['RT:1', 'RT:2', 'Other', 'Stuff'],
count = startArray.filter(item => regixForRTStart.test(item))
// length
console.log(count.length);
use filter and startsWith methods.
const arr = [
{ message: "abc" },
{ message: "RT:" },
{ message: "RT: 2" },
{ message: "test" }
];
const count = arr.filter(({ message }) => message.startsWith("RT:")).length;
console.log(count);

How to update Array field?

Im using Firebase Firestore and want to update an array field under a userprofile with the latest chat thread's id.. Im guessing that I have to pull the entire array (if it exists) from the chat node under that user, then I need to append the new id (if it doesnt exist) and update the array.. It works when theres only 1 value in the array then it fails after that with the following error:
Transaction failed: { Error: Cannot convert an array value in an array value.
at /user_code/node_modules/firebase-admin/node_modules/grpc/src/node/src/client.js:554:15 code: 3, metadata: Metadata { _internal_repr: {} } }
and here is my firebase cloud function, can anyone tell me where im going wrong ?
exports.updateMessages = functions.firestore.document('messages/{messageId}/conversation/{msgkey}').onCreate( (event) => {
/// console.log('function started');
const messagePayload = event.data.data();
const userA = messagePayload.userA;
const userB = messagePayload.userB;
// console.log("userA " + userA);
// console.log("userB " + userB);
// console.log("messagePayload " + JSON.stringify(messagePayload, null, 2) );
const sfDocRef = admin.firestore().doc(`users/${userB}`);
return admin.firestore().runTransaction( (transaction) => {
return transaction.get(sfDocRef).then( (sfDoc) => {
const array = [];
array.push(...[event.params.messageId, sfDoc.get('chats') ]);
transaction.update(sfDocRef, { chats: array } );
});
}).then( () => {
console.log("Transaction successfully committed!");
}).catch( (error) => {
console.log("Transaction failed: ", error);
});
});
You're nesting arrays in your code here:
const array = [];
array.push(...[event.params.messageId, sfDoc.get('chats') ]);
This leads to an array with two values, the first one being the new messageId and the second value contains an array all of your previous values, e.g.
[ "new message id", ["previous id", "older id"] ]
This type of nested array is something that Firestore (apparently) doesn't allow to be stored.
The solution is simple:
const array = [event.params.messageId, ...sfDoc.get('chats')];
The fact that you have to first load the array to then add a single element to it is one of reasons Firebasers recommend not storing data in arrays. Your current data looks like it'd be better off as a set, as shown in the Firestore documenation:
{
"new message id": true,
"previous id": true,
"older id": true
}
That way adding a chat ID is as simple as:
sfDocRef.update({ "chats."+event.params.messageId, true })
I have looked further into the matter, and I would follow the advice that Frank gave you in his post; allocate the data in collections rather than with arrays as they have greater versatility for Firebase 1. Researching under the examples listed in the Firebase website looking for anything related to a chat, I’ve found the data structure and code for messages that are used by Firechat as they might be of use for you.
In the source code, they use a collection for the their message-id -userId pair with the following topology 2 :
The exact way how the saving is executed at the repository is 3 :
It executes an append of the message into the Room-id collection. Instead of this structure, you could use an userID - messageID pair as it might fit you better.

Using a string as a priority in Firebase

I read with interest the blog post here, which describes how to make a query equivalent to sql WHERE email = x
new Firebase("https://examples-sql-queries.firebaseio.com/user")
.startAt('kato#firebase.com')
.endAt('kato#firebase.com')
.once('value', function(snap) {
console.log('accounts matching email address', snap.val())
});
I've tried to replicate this as follows:
root
|-rewards
|--JAJoFho0MYBMGNGrCdc
|-name: "apple"
|--JAJoFj7KsLSXMdGZ77V
|-name: "orange"
|--JAJoFp7HP6Ajq-VuMMx
|-name: "banana"
There are many other fields in each rewards object... but I want to index the object by name and to be able to query all these objects to find the one matching a given name. The blog post instructs us to use setPriority() to achieve this.
I have tried the following:
var ref = new Firebase('https://<example>.firebaseio.com/rewards').push({
name: 'apple',
otherKey: 'somevalue',
...
});
ref.setPriority('apple');
If I then query firebase, it returns null:
new Firebase('https://<example>.firebaseio.com/rewards')
.startAt('apple')
.endAt('apple')
.once('value', function(snap) {
console.log('found:', snap.val()); // logs: "found null"
});
What am I doing wrong?
Looks like you're attempting to run these commands synchronously. At the time that you request rewards, there may not be any data yet (your push ops may not have finished).
Next, you should use setWithPriority, which will allow you to push the data and priority at the same time.
Last but not least, you haven't mentioned errors. I'll assume you checked those like any diligent dev would. In addition to the JS console, you can log the results of the callback functions (there's one for each of the methods you called, which could return an error if something went wrong).
So all together, it should look more like this:
var ref = new Firebase('https://<example>.firebaseio.com/rewards').push();
ref.setWithPriority({
name: 'apple',
otherKey: 'somevalue',
...
}, 'apple', function(err) {
if( error ) { console.error(err); }
else {
fetchValue();
}
});
function fetchValue() {
// wait for the set to complete before fetching data
new Firebase('https://<example>.firebaseio.com/rewards')
.startAt('apple')
.endAt('apple')
.once('value', function(snap) {
console.log('found:', snap.val()); // logs: "found null"
});
}

Categories

Resources