| var events = require('events') |
| |
| var Promise = require('bluebird') |
| var syrup = require('stf-syrup') |
| |
| var logger = require('../../../util/logger') |
| var wire = require('../../../wire') |
| var wireutil = require('../../../wire/util') |
| var grouputil = require('../../../util/grouputil') |
| var lifecycle = require('../../../util/lifecycle') |
| |
| module.exports = syrup.serial() |
| .dependency(require('./solo')) |
| .dependency(require('./util/identity')) |
| .dependency(require('./service')) |
| .dependency(require('../support/router')) |
| .dependency(require('../support/push')) |
| .dependency(require('../support/sub')) |
| .dependency(require('../support/channels')) |
| .define(function(options, solo, ident, service, router, push, sub, channels) { |
| var log = logger.createLogger('device:plugins:group') |
| var currentGroup = null |
| var plugin = new events.EventEmitter() |
| |
| plugin.get = Promise.method(function() { |
| if (!currentGroup) { |
| throw new grouputil.NoGroupError() |
| } |
| |
| return currentGroup |
| }) |
| |
| plugin.join = function(newGroup, timeout, identifier) { |
| var joinNewGroup = function() { |
| currentGroup = newGroup; |
| |
| log.important('Now owned by "%s".', currentGroup.email); |
| log.info('Subscribing to group channel "%s".', currentGroup.group); |
| |
| channels.register(currentGroup.group, { |
| timeout: timeout || options.groupTimeout, |
| alias: solo.channel |
| }); |
| |
| sub.subscribe(currentGroup.group); |
| |
| push.send([ |
| wireutil.global, |
| wireutil.envelope(new wire.JoinGroupMessage( |
| options.serial, |
| currentGroup)) |
| ]); |
| |
| plugin.emit('join', currentGroup, identifier); |
| |
| return currentGroup; |
| }; |
| |
| return plugin.get().then(function() { |
| if (currentGroup.group !== newGroup.group) { |
| return plugin.leave('kick').then(function() { |
| return joinNewGroup(); |
| }); |
| } |
| |
| return currentGroup; |
| }).catch(grouputil.NoGroupError, joinNewGroup); |
| }; |
| |
| plugin.keepalive = function() { |
| if (currentGroup) { |
| channels.keepalive(currentGroup.group) |
| } |
| } |
| |
| plugin.leave = function(reason) { |
| return plugin.get() |
| .then(function(group) { |
| log.important('No longer owned by "%s"', group.email) |
| log.info('Unsubscribing from group channel "%s"', group.group) |
| |
| channels.unregister(group.group) |
| sub.unsubscribe(group.group) |
| |
| push.send([ |
| wireutil.global |
| , wireutil.envelope(new wire.LeaveGroupMessage( |
| options.serial |
| , group |
| , reason |
| )) |
| ]) |
| |
| currentGroup = null |
| plugin.emit('leave', group) |
| |
| return group |
| }) |
| } |
| |
| plugin.on('join', function() { |
| service.wake() |
| service.acquireWakeLock() |
| }) |
| |
| plugin.on('leave', function() { |
| service.pressKey('home') |
| service.thawRotation() |
| service.releaseWakeLock() |
| }) |
| |
| router |
| .on(wire.GroupMessage, function(channel, message) { |
| var reply = wireutil.reply(options.serial) |
| grouputil.match(ident, message.requirements) |
| .then(function() { |
| return plugin.join(message.owner, message.timeout) |
| }) |
| .then(function() { |
| push.send([ |
| channel |
| , reply.okay() |
| ]) |
| }) |
| .catch(grouputil.RequirementMismatchError, function(err) { |
| push.send([ |
| channel |
| , reply.fail(err.message) |
| ]) |
| }) |
| .catch(grouputil.AlreadyGroupedError, function(err) { |
| push.send([ |
| channel |
| , reply.fail(err.message) |
| ]) |
| }) |
| }) |
| .on(wire.AutoGroupMessage, function(channel, message) { |
| return plugin.join(message.owner, message.timeout, message.identifier) |
| .then(function() { |
| plugin.emit('autojoin', message.identifier, true) |
| }) |
| .catch(grouputil.AlreadyGroupedError, function() { |
| plugin.emit('autojoin', message.identifier, false) |
| }) |
| }) |
| .on(wire.UngroupMessage, function(channel, message) { |
| var reply = wireutil.reply(options.serial) |
| grouputil.match(ident, message.requirements) |
| .then(function() { |
| return plugin.leave('ungroup_request') |
| }) |
| .then(function() { |
| push.send([ |
| channel |
| , reply.okay() |
| ]) |
| }) |
| .catch(grouputil.NoGroupError, function(err) { |
| push.send([ |
| channel |
| , reply.fail(err.message) |
| ]) |
| }) |
| }) |
| |
| channels.on('timeout', function(channel) { |
| if (currentGroup && channel === currentGroup.group) { |
| plugin.leave('automatic_timeout') |
| } |
| }) |
| |
| lifecycle.observe(function() { |
| return plugin.leave('device_absent') |
| .catch(grouputil.NoGroupError, function() { |
| return true |
| }) |
| }) |
| |
| return plugin |
| }) |