Code Monkey home page Code Monkey logo

socialize-user-presence's Introduction

User Presence

This package is a simple, scalable package for keeping track of if your users are online, idle, or offline. While other packages exist that do this same thing, most of them fall flat when it comes to scalability and they lock you into keeping the status data on the profile key of the user record. This package allows you to clean up neatly after an app instance dies and lets you configure what actions to take when the users presence changes state.

This is a Meteor package with part of it's code published as a companion NPM package made to work with clients other than Meteor. For example your server is Meteor, but you want to build a React Native app for the client. This allows you to share code between your Meteor server and other clients to give you a competitive advantage when bringing your mobile and web application to market.

Supporting The Project

Finding the time to maintain FOSS projects can be quite difficult. I am myself responsible for over 30 personal projects across 2 platforms, as well as Multiple others maintained by the Meteor Community Packages organization. Therfore, if you appreciate my work, I ask that you either sponsor my work through GitHub, or donate via Paypal or Patreon. Every dollar helps give cause for spending my free time fielding issues, feature requests, pull requests and releasing updates. Info can be found in the "Sponsor this project" section of the GitHub Repo

Meteor Installation

This package does not directly use the simpl-schema package, but it depend on the socialize:user-model which uses it and so we need to make sure it's installed as well

meteor npm install --save simpl-schema
meteor add socialize:user-presence

NPM Installation

When using this package with React Native, the dependency tree ensures that simpl-schema is loaded so there's no need to install it as when using within Meteor.

npm install --save @socialize/user-presence

Usage Outside Meteor

The client side parts of this package are published to NPM as @socialize/cloudinary for use in front ends outside of Meteor.

When using the npm package you'll need to connect to a server, which hosts the server side Meteor code for your app, using Meteor.connect as per the @socialize/react-native-meteor usage example documentation.

Meteor.connect('ws://192.168.X.X:3000/websocket');

React Native

When using this package with React Native there is some minor setup required by the @socialize/react-native-meteor package. See @socialize/react-native-meteor react-native for necessary instructions.

Basic Usage

We first need to configure how presence works on the server. This part won't work in React Native code, so you won't find React Native specific code here.

import { Meteor } from 'meteor/meteor';
import { User } from 'meteor/socialize:user-model';
import { UserPresence } from 'meteor/socialize:user-presence';
import SimpleSchema from 'simpl-schema';

// Schema for the fields where we will store the status data
const StatusSchema = new SimpleSchema({
    status: {
        type: String,
        optional: true,
        allowedValues: ['online', 'idle'],
    },
    lastOnline: {
        type: Date,
        optional: true,
    },
});

// Add the schema to the existing schema currently attached to the User model
User.attachSchema(StatusSchema);

// If `sessionIds` is undefined this signifies we need a fresh start.
// When a full cleanup is necessary we will unset the status field to show all users as offline
UserPresence.onCleanup(function onCleanup(sessionIds) {
    if (!sessionIds) {
        Meteor.users.update({}, { $unset: { status: true } }, { multi: true });
    }
});

// When a user comes online we set their status to online and set the lastOnline field to the current time
UserPresence.onUserOnline(function onUserOnline(userId) {
    Meteor.users.update(userId, { $set: { status: 'online', lastOnline: new Date() } });
});

// When a user goes idle we'll set their status to indicate this
UserPresence.onUserIdle(function onUserIdle(userId) {
    Meteor.users.update(userId, { $set: { status: 'idle' } });
});

// When a user goes offline we'll unset their status field to indicate offline status
UserPresence.onUserOffline(function onUserOffline(userId) {
    Meteor.users.update(userId, { $unset: { status: true } });
});

Server API

The server side API consists of methods which register callbacks to run when a users presence changes. A user is considered online if any session is set to online, idle if all sessions are set to idle, or offline if there are no current sessions for the user.

UserPresence.onSessionConnected(Fn(connection, userId)) - register a callback to run each time a logged in user makes a connection to the server.

UserPresence.onSessionConnected(function(connection, userId){
    EventLogs.insert({eventType: 'user-connected', userId, connection});
});

UserPresence.onSessionDisconnected(Fn(connection, userId)) - register a callback to run each time a logged in user breaks connection to the server.

UserPresence.onSessionDisconnected(function (connection, userId) {
    EventLogs.insert({eventType: 'user-disconnected', userId, connection});
});

UserPresence.onCleanup(Fn()) - register a callback to run when your application starts fresh without any other instances running. T

UserPresence.onCleanup(function () {
    Meteor.users.update({}, { $unset: { status: true } }, { multi: true });
});

UserPresence.onUserOnline(Fn(userId, connection)) - register a callback to run when the users status is "Online" (Any one session is online).

UserPresence.onUserOnline(function (userId) {
    ProfilesCollection.update({ _id: userId }, { $set: { status: 'online' } });
});

UserPresence.onUserIdle(Fn(userId, connection)) - register a callback to run when the users status is "Idle" (All sessions are idle)

UserPresence.onUserIdle(function (userId) {
    ProfilesCollection.update({ _id: userId }, { $set: { status: 'idle' } });
});

UserPresence.onUserOffline(Fn(userId, connection)) - register a callback to run when the users status is "Offline" (No connected sessions)

UserPresence.onUserOffline(function (userId) {
    ProfilesCollection.update({ _id: userId }, { $unset: { status: true } });
});

User Extensions

This package provides some extensions onto the User class which comes with socialize:user-model for your convenience. These methods are included in the React Native code and so if using this package in React Native, you'll need to import the package for it to properly extend the User class with these methods.

import '@socialize/user-presence';
// Now Meteor.user() will return instances of 'User' class with these methods available

User.prototype.setStatusIdle() - Set the current logged in user for this session to idle.

Meteor.user().setStatusIdle();

User.prototype.setStatusOnline() - Set the current logged in user for this session to online.

Meteor.user().setStatusOnline();

socialize-user-presence's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

socialize-user-presence's Issues

ReferenceError: determineStatus is not defined

Client: Error: invoking Method 'updateSessionStatus': Internal server error [500]
Server: ReferenceError: determineStatus is not defined
when we call Meteor.user().setStatusOnline();
because determineStatus is not globally defined.

onUserOffline is not working

Hi,

onUserOffline not fires up. I've just added it like this on server:

UserPresence.onUserOnline(function(userId){                                                                                                                                               
    Meteor.users.update({_id:userId}, {$set:{'profile.status':"online"}})                                                                                                                 
});                                                                                                                                                                                       

UserPresence.onUserOffline(function(userId){                                                                                                                                              
console.log(userId);                                                                                                                                                                      
    Meteor.users.update({_id:userId}, {$set:{'profile.status':"offline"}})                                                                                                                
});                                                                                                                                                                                       

onUserOnline - work fine.
But on Offline - nothing happens. Console.log not works too.

Any suggestions?

Thank you.

dependencies

This package has a lot of dependencies.

aldeed:collection2               added, version 2.3.3
matb33:collection-hooks          added, version 0.7.15
meteorhacks:unblock              added, version 1.1.0
socialize:base-model             added, version 0.2.3
socialize:server-presence        added, version 0.1.2
socialize:server-time            added, version 0.1.2
socialize:user-model             added, version 0.1.4
socialize:user-presence          added, version 0.2.1
tmeasday:publish-with-relations  added, version 0.2.0

Most of them are from socialize:user-model which depends on socialize-base-model. Can user-model be removed or made optional? Is common/user-extensions.js the only place it's used?

HCP does not reflect server-side modified code changes

When the package is imported to meteor project, the "Hot Code Push" of Meteor (from server side code) seems not to be working because the changes are not reflected. In the console only shows Meteor server restarted but when I invoke again a meteor method it executes the old code. To see the changes I have to disconnect and connect the ddp client or reload the browser.

I verified this behavior in different apps and even, I create a basic meteor project and I only added 2 packages: socialize:user-presence and mdg:validated-method. and the issue is still present.

You can reproduce this issue following the next steps:

  1. meteor create app-with-user-presence
  2. cd app-with-user-presence
  3. meteor add socialize:user-presence mdg:validated-method
  4. replace the content of server/main.js with the following code:
import { ValidatedMethod } from 'meteor/mdg:validated-method';

new ValidatedMethod({
	name: 'testMethod',
	validate: null,
	run() {
		console.log('entry 4');//Change the number to test
		return { hello: 'world 4' };//Change the number to test
	}
});
  1. run meteor app: meteor
  2. invoke the meteor method (with meteor shell, ddp-tools or Meteorman)
  3. modify the meteor method and wait for "meteor server restarted" (to provoke this, maybe you should change by some moments to another app, e.g. browser, meteorman, etc)
  4. invoke again the meteor method and verify the modified code is not reflected.
  5. After that, you can remove socialize:user-presence and test again.
  6. verify that the modified code is now reflected without socialize:user-presence package.

You can use this mini project to verify it:

app-with-user-presence.zip

You can use Meteorman to test meteor methods.

No userId in connection object

I'm trying to use onSessionConnected method on server side, but there is no userId field in connection object.

Connection object:

{ 
  id: 'fc3LM2KyNs2GTvNo7',
  close: [Function: close],
  onClose: [Function: onClose],
  clientAddress: '127.0.0.1',
  httpHeaders: { 
    'x-forwarded-for': '127.0.0.1',
    'x-forwarded-proto': 'ws',
    host: 'localhost:3000',
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50' 
  } 
}

How can I get userId for connection?
Thanks.

How it use?

How to use it in the application?
I can not update the status of the user.

Undefined connection.userId

In

UserPresence.onSessionConnected(function(connection){
var userId = connection.userId;
});

run on the server, userId is always undefined. Any idea why?

Thanks!

Cannot read property 'RegEx' of undefined

Hi @copleykj , I'm trying to migrate from mizzao:user-status to this package due to a issue in the another package, however, I can't run my meteor app because appears this error:

W20201111-17:45:48.661(-6)? (STDERR) /Users/diavrank/.meteor/packages/meteor-tool/.1.11.1.95af9c.g0b4t++os.osx.x86_64+web.browser+web.browser.legacy+web.cordova/mt-os.osx.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:280
W20201111-17:45:48.683(-6)? (STDERR) 						throw(ex);
W20201111-17:45:48.683(-6)? (STDERR) 						^
W20201111-17:45:48.683(-6)? (STDERR) 
W20201111-17:45:48.683(-6)? (STDERR) TypeError: Cannot read property 'RegEx' of undefined
W20201111-17:45:48.683(-6)? (STDERR)     at module (packages/socialize:linkable-model/common/linkable-model.js:50:28)
W20201111-17:45:48.683(-6)? (STDERR)     at fileEvaluate (packages/modules-runtime.js:336:7)
W20201111-17:45:48.684(-6)? (STDERR)     at Module.require (packages/modules-runtime.js:238:14)
W20201111-17:45:48.684(-6)? (STDERR)     at Module.moduleLink [as link] (/Users/diavrank/.meteor/packages/modules/.0.15.0.tjvg00.6lcb++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/reify/lib/runtime/index.js:52:22)
W20201111-17:45:48.684(-6)? (STDERR)     at module (packages/socialize:linkable-model/common/common.js:1:8)
W20201111-17:45:48.684(-6)? (STDERR)     at fileEvaluate (packages/modules-runtime.js:336:7)
W20201111-17:45:48.684(-6)? (STDERR)     at Module.require (packages/modules-runtime.js:238:14)
W20201111-17:45:48.684(-6)? (STDERR)     at require (packages/modules-runtime.js:258:21)
W20201111-17:45:48.684(-6)? (STDERR)     at /Users/diavrank/Documents/monitoreo-sismos/.meteor/local/build/programs/server/packages/socialize_linkable-model.js:149:15
W20201111-17:45:48.684(-6)? (STDERR)     at /Users/diavrank/Documents/monitoreo-sismos/.meteor/local/build/programs/server/packages/socialize_linkable-model.js:154:3
W20201111-17:45:48.685(-6)? (STDERR)     at /Users/diavrank/Documents/monitoreo-sismos/.meteor/local/build/programs/server/boot.js:401:38
W20201111-17:45:48.685(-6)? (STDERR)     at Array.forEach (<anonymous>)
W20201111-17:45:48.685(-6)? (STDERR)     at /Users/diavrank/Documents/monitoreo-sismos/.meteor/local/build/programs/server/boot.js:226:21
W20201111-17:45:48.685(-6)? (STDERR)     at /Users/diavrank/Documents/monitoreo-sismos/.meteor/local/build/programs/server/boot.js:464:7
W20201111-17:45:48.685(-6)? (STDERR)     at Function.run (/Users/diavrank/Documents/monitoreo-sismos/.meteor/local/build/programs/server/profile.js:280:14)
W20201111-17:45:48.685(-6)? (STDERR)     at /Users/diavrank/Documents/monitoreo-sismos/.meteor/local/build/programs/server/boot.js:463:13

My code is the following:

import { Meteor } from 'meteor/meteor';
import { User } from 'meteor/socialize:user-model';
import { UserPresence } from 'meteor/socialize:user-presence';
import Utilities from '../../startup/server/Utilities';
import SimpleSchema from 'simpl-schema';

// Schema for the fields where we will store the status data
const StatusSchema = new SimpleSchema({
	status: Object,
	'status.online': { type: Boolean },
	'status.idle': { type: Boolean, optional: true },
	'status.lastLogin': Object
});

// Add the schema to the existing schema currently attached to the User model
User.attachSchema(StatusSchema);

// If `sessionIds` is undefined this signifies we need a fresh start.
// When a full cleanup is necessary we will unset the status field to show all users as offline
UserPresence.onCleanup(function onCleanup(sessionIds) {
	if (!sessionIds) {
		console.log('cleanup sessionIds executed');
		Meteor.users.update({}, { $set: { 'status.online': false }, $unset: { 'status.idle': true } }, { multi: true });
	}
});

// When a user comes online we set their status to online and set the lastOnline field to the current time
UserPresence.onUserOnline(function onUserOnline(userId, connection) {
	console.log('connection: ', connection);
	Meteor.users.update(userId, { $set: { 'status.online': true, 'lastLogin.date': Utilities.currentLocalDate() } });
});

// When a user goes idle we'll set their status to indicate this
UserPresence.onUserIdle(function onUserIdle(userId) {
	Meteor.users.update(userId, { $set: { 'status.idle': false } });
});

// When a user goes offline we'll unset their status field to indicate offline status
UserPresence.onUserOffline(function onUserOffline(userId) {
	Meteor.users.update(userId, { $set: { 'status.online': false }, $unset: { 'status.idle': true } });
});

I already added the necessary packages and it doesn't work :( .

Meteor packages:

  • socialize:user-presence
  • aldeed:simple-schema

Yarn dependency:

  • simpl-schema

(I also tried it with npm but neither work)

Do you know what could be the problem?

[Question] When is idle status activated?

Hello Kelly, I was reading the server API and I wonder in which cases idle status can be enabled?

I saw that exists a method Meteor.user().setStatusIdle() , however, I have doubt if also exists a default timeout to detect inactivity of the user and enable idle status automatically.

it happens that I have a monitoring application and I am getting a weird behavior, since devices (users) are disconnected after the 3rd or 5th day. In some cases, they're reconnected automatically (this is good) but in other cases they remain offline.

image

In the monitoring view I am only using two status: online and offline, if online property is true then the icon is green, otherwise is red. So, I am suspecting if "idle" is active in those cases, that is the possible reason they keep in red, so that's why my question.

On the other hand, I wonder if you have had a similar situation of this:

I am getting a weird behavior, since devices (users) are disconnected after the 3rd or 5th day.

Notes:

Server:

Client:

  • Simple DDP Client
  • Asus Tinker Boards (SBC) with Debian OS
  • Node 12/14
  • It is worth mentioning that these devices at the moment do not make calls to endpoints (methods and publications), only the time in which they remain with online status is being measured.

Front-end of web admin is using Vue since they are real users who operate the system.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.