Accessing published Meteor data - javascript

Not sure if I'm going about this the right way. I'll map out what I'm trying to achieve and please give me any feedback you can. Also very new to meteor so sorry if I'm a bit uneducated in some aspects. This is going to be a two player game where users login in with accounts-twitter or accounts-facebook. Here's the tricky part it will only initialize the game if there are two users logged in. To figure out who is logged in I have put this line of code in my server portion:
if (Meteor.isServer) {
Meteor.publish("userStatus", function() {
return Meteor.users.find({
"status.online": true
})
});
}
My idea of what needs to be done is write an if statement if(userStatus === true){get a users "_id"} then push that user into an array and have a for loop run through every 2 users signed on in the array and initialize a game for them. Also the main question is how do I grab the users ID if status.online is true? Also any input on how to make this more efficient is much appreciated.

Answering your "main question," you would do this with a mongoDB for-each like so.
Meteor.methods({
getOnline : function(){
var retArr = new Array();
Meteor.users.find({"status.online": true}).forEach(function(u){
retArr.push(u._id); //populated retArr with the id of users online
});
return retArr;
}
});
If I left out something or you need clarification on something, please comment.

Related

Creating increment limit

Ok so I am making a like/dislike system for my website and I got it to work. The only problem is, is that a user can like something more than once, how do I stop this? heres my function
function thumbup(uid, s) {
const prevthumbs = s.thumbs
firebase.db.collection('users').doc(uid).update({
thumbs: prevthumbs + 1
})
}
How can I limit the increment to only one?
To limit how often the user can do something, use their UID as the key for the operation.
For example, if you don't have too many users, you can have a field likedBy in the document which is an array of the UIDs of the users who liked this user.
It's a bit unclear how to exactly implement it in your code for me, as you're already writing to a doc(uid), where usually the user is liking a post or something like that.

How do I display the followers count in real time using firebase?

I have an application where users can follow other users. I want to have a real-time update system, display the total count of followers a user has.
I've just started playing around with Firebase and Pusher, but I don't understand one thing - will each user have their own 'channel'? How would I handle such thing as a follower counter update?
I followed the tutorial and saw that push method can create lists, so one solution I can see is having a list of all the users, each user being an object something like this:
{ username: 'john_doe', follower_count: 6 }
But I don't understand how would I actually track it on the front end? Should I have a filter, something like this?
var user = users.filter(function(user) { return user.username === 'john_doe'; });
// code to display user.follower_count
Or is there a different way that I'm missing?
Most of Firebase logic is based on listeners, you can add a listener to events happening in your collections and when those events happen, you do something.
One way to go about this would be:
var myFollowerListRef = new Firebase(PATH_TO_YOUR_COLLECTION);
myFollowerListRef.on("value", function(snapshot) {
console.log(snapshot.length);
});
This way, every time your follower collection changes, the asynchronous function fires and you can do what you want with the fresh data.
For more information:
https://www.firebase.com/docs/web/guide/retrieving-data.html
Hope this helps, I'm still a beginner in Firebase.
#Th0rndike's approach is the simplest and works fine for relatively short lists. For longer lists, consider using a transaction. From the Firebase documentation on saving transactional data:
var upvotesRef = new Firebase('https://docs-examples.firebaseio.com/android/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes');
upvotesRef.transaction(function (current_value) {
return (current_value || 0) + 1;
});
But I recommend that you read the entire Firebase guide. It contains solutions for a lot of common use-cases.

sorting each session uniquely in Meteor?

I have publishing setup along with sessions to send out messages to the right rooms.
I'm currently having issues as to how do I go about limiting returned messages so if a room has, say, 200 messages in it and another one is posted, the oldest one is deleted.
//how messages are created
Meteor.methods({
newMessage: function (message) {
message.user = Meteor.userId();
Messages.insert(message);
}
});
//how messages are published
Meteor.publish('messages', function (channel) {
return Messages.find({channel: channel});
});
//how chatrooms are published
Meteor.publish('channels', function () {
return Channels.find();
});
Problem is, normally I would do this by putting this in the publications {sort:{limit:15}}
However, that doesn't work in this case and results in ALL of the messages being limited.
They need to be sorted by room, or, well, per session:key.
Is there a simple way of going about this? Or would I have to make a method on the serverside to run .forEach channel?
There's no decent way of publishing the top 15 posts from each room in a single cursor. If the number of rooms is small it might make sense to publish an array of cursors instead, each cursor in the array corresponding to a single room.
Meteor.publish('messages', function (channel) {
return Messages.find({channel: channel}, {limit: 15});
});
I have no idea how I missed this but apparently I can just do it this way.
Huh.
(channel:channel corresponds to currently set session's name)

Meteor Leaderboard example: resetting the scores

I've been trying to do Meteor's leaderboard example, and I'm stuck at the second exercise, resetting the scores. So far, the furthest I've got is this:
// On server startup, create some players if the database is empty.
if (Meteor.isServer) {
Meteor.startup(function () {
if (Players.find().count() === 0) {
var names = ["Ada Lovelace",
"Grace Hopper",
"Marie Curie",
"Carl Friedrich Gauss",
"Nikola Tesla",
"Claude Shannon"];
for (var i = 0; i < names.length; i++)
Players.insert({name: names[i]}, {score: Math.floor(Random.fraction()*10)*5});
}
});
Meteor.methods({
whymanwhy: function(){
Players.update({},{score: Math.floor(Random.fraction()*10)*5});
},
}
)};
And then to use the whymanwhy method I have a section like this in if(Meteor.isClient)
Template.leaderboard.events({
'click input#resetscore': function(){Meteor.call("whymanwhy"); }
});
The problem with this is that {} is supposed to select all the documents in MongoDB collection, but instead it creates a new blank scientist with a random score. Why? {} is supposed to select everything. I tried "_id" : { $exists : true }, but it's a kludge, I think. Plus it behaved the same as {}.
Is there a more elegant way to do this? The meteor webpage says:
Make a button that resets everyone's score to a random number. (There
is already code to do this in the server startup code. Can you factor
some of this code out and have it run on both the client and the
server?)
Well, to run this on the client first, instead of using a method to the server and having the results pushed back to the client, I would need to explicitly specify the _ids of each document in the collection, otherwise I will run into the "Error: Not permitted. Untrusted code may only update documents by ID. [403]". But how can I get that? Or should I just make it easy and use collection.allow()? Or is that the only way?
I think you are missing two things:
you need to pass the option, {multi: true}, to update or it will only ever change one record.
if you only want to change some fields of a document you need to use $set. Otherwise update assumes you are providing the complete new document you want and replaces the original.
So I think the correct function is:
Players.update({},{$set: {score: Math.floor(Random.fraction()*10)*5}}, {multi:true});
The documentation on this is pretty thorough.

How to create discincts JS methodes in Spotify App

I've been working on a small Spotify app for some time now. I started using the old API (0.x) but now that I want to access the user's playlists, I need to use the library module which is only available throught the API version 1.0
The spotify team even gives a migration guide to do so ! (if you read me: Thanks guys for all this ;) ).
I already have created a few objects (It's a small app so I don't need much more than that), with a function for each one of my needs, like so:
var sp = getSpotifyApi();
var models = require('sp://import/scripts/api/models');
var player = models.player;
var views = require('sp://import/scripts/api/views');
// in file 'mySpotify.js'
var mySpotify =
{
playerNextTrack: function()
{
player.next();
},
}
Whenever I need to Skip the current track, I can call mySpotify.playerNextTrack();
But now, with the new API, I need to do things like this (from Spotify doc):
require(['$api/models'], function(models) {
var player = models.player;
player.next();
});
My question is simple: how can I include this kind of code into my objects ? How can I give a name to this last "function" ?
As I'm fresh new to JS, I'm probably doing something wrong or understood something the wrong way so feel free to elaborate if you can ;)
I'll start with what I think is the easy answer, just put the require([], function {[all your code]}); around your whole myspotify.js file. That's basically what I have for mine, though I haven't built any of my own objects. Don't think that would matter.
Update
Here's a bit more info showing that objects can be used. Is this what you were looking for?
require(['$api/models'], function(models) {
var mySpotify =
{
playerNextTrack: function()
{
models.player.skipToNextTrack();
},
}
var playtest = document.querySelector('#playtest');
playtest.addEventListener('click', function() { mySpotify.playerNextTrack(); });
});

Categories