nodebb-plugin-shoutbox
Advanced tools
Comparing version 0.1.0 to 0.2.0
@@ -9,7 +9,8 @@ var async = require('async'), | ||
Backend = { | ||
addShout: function(fromuid, content, callback) { | ||
(function(Backend) { | ||
Backend.addShout = function(fromuid, content, callback) { | ||
db.incrObjectField('global', 'nextSid', function(err, sid) { | ||
if (err) { | ||
return callback(err, null); | ||
return callback(err); | ||
} | ||
@@ -24,11 +25,17 @@ | ||
db.setObject('shout:' + sid, shout); | ||
db.listAppend('shouts', sid); | ||
db.setObject('shout:' + sid, shout, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
Backend.updateShoutTime(fromuid); | ||
shout.sid = sid; | ||
callback(null, shout); | ||
db.listAppend('shouts', sid); | ||
getShouts([sid], true, function(err, shouts) { | ||
callback(err, shouts ? shouts[0] : null); | ||
}); | ||
}); | ||
}); | ||
}, | ||
getShout: function(sid, callback) { | ||
}; | ||
Backend.getRawShout = function(sid, callback) { | ||
db.getObject('shout:' + sid, function(err, shout) { | ||
@@ -40,7 +47,8 @@ if (err) { | ||
}); | ||
}, | ||
getShouts: function(start, end, callback) { | ||
}; | ||
Backend.getShouts = function(start, end, callback) { | ||
db.getListRange('shouts', start, end, function(err, sids) { | ||
if (err) { | ||
return callback(err, null); | ||
return callback(err); | ||
} | ||
@@ -52,35 +60,60 @@ | ||
function getShout(sid, next) { | ||
db.getObject('shout:' + sid, function(err, message) { | ||
if (err) { | ||
return next(err); | ||
} | ||
if (message.deleted === '1') { | ||
getShouts(sids, false, callback); | ||
}); | ||
}; | ||
function getShouts(sids, isNew, callback) { | ||
var keys = sids.map(function(sid) { | ||
return 'shout:' + sid; | ||
}); | ||
db.getObjects(keys, function(err, shouts) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
var userData, uids = shouts.map(function(s) { | ||
return parseInt(s.deleted, 10) !== 1 ? parseInt(s.fromuid, 10) : null; | ||
}).filter(function(u, index, self) { | ||
return u === null ? false : self.indexOf(u) === index; | ||
}); | ||
User.getMultipleUserFields(uids, ['username', 'userslug', 'picture', 'status'], function(err, usersData) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
shouts = shouts.map(function (shout, index) { | ||
shout.sid = sids[index]; | ||
return shout; | ||
}); | ||
async.map(shouts, function(shout, next) { | ||
if (parseInt(shout.deleted, 10) === 1) { | ||
return next(null); | ||
} | ||
User.getMultipleUserFields([message.fromuid], ['username', 'userslug', 'picture', 'status'], function(err, userData) { | ||
userData = userData[0]; | ||
userData.uid = message.fromuid; | ||
Backend.parse(message.content, userData, false, function(err, data) { | ||
message.user = data.userData; | ||
message.user.isAdmin = data.isAdmin; | ||
message.isNew = data.isNew; | ||
message.content = data.content; | ||
message.sid = sid; | ||
next(null, message); | ||
}); | ||
userData = usersData[uids.indexOf(parseInt(shout.fromuid))]; | ||
userData.uid = shout.fromuid; | ||
Backend.parse(shout.content, userData, isNew, function(err, s) { | ||
shout.user = s.user; | ||
shout.isNew = s.isNew; | ||
shout.content = s.content; | ||
next(null, shout); | ||
}); | ||
}); | ||
} | ||
}, callback); | ||
}); | ||
}); | ||
} | ||
async.map(sids, getShout, callback); | ||
}); | ||
}, | ||
parse: function(message, userData, isNew, callback) { | ||
Backend.parse = function(message, userData, isNew, callback) { | ||
Plugins.fireHook('filter:post.parse', message, function(err, parsed) { | ||
User.isAdministrator(userData.uid, function(err, isAdmin) { | ||
userData.status = NodeBB.SocketIndex.isUserOnline(userData.uid) ? (userData.status || 'online') : 'offline'; | ||
userData.isAdmin = isAdmin; | ||
var shout = { | ||
userData: userData, | ||
isAdmin: isAdmin, | ||
user: userData, | ||
isNew: isNew, | ||
@@ -93,4 +126,5 @@ content: parsed | ||
}); | ||
}, | ||
removeShout: function(sid, uid, callback) { | ||
}; | ||
Backend.removeShout = function(sid, uid, callback) { | ||
User.isAdministrator(uid, function(err, isAdmin) { | ||
@@ -101,2 +135,3 @@ db.getObjectField('shout:' + sid, 'fromuid', function(err, fromuid) { | ||
} | ||
if (fromuid === uid || isAdmin) { | ||
@@ -114,4 +149,5 @@ db.setObjectField('shout:' + sid, 'deleted', '1', function (err, result) { | ||
}); | ||
}, | ||
editShout: function(sid, msg, uid, callback) { | ||
}; | ||
Backend.editShout = function(sid, msg, uid, callback) { | ||
User.isAdministrator(uid, function(err, isAdmin) { | ||
@@ -122,2 +158,3 @@ db.getObjectField('shout:' + sid, 'fromuid', function(err, fromuid) { | ||
} | ||
if (fromuid === uid || isAdmin) { | ||
@@ -128,14 +165,5 @@ db.setObjectField('shout:' + sid, 'content', msg, function (err, result) { | ||
} | ||
User.getMultipleUserFields([fromuid], ['username', 'userslug', 'picture', 'status'], function(err, userData) { | ||
userData = userData[0]; | ||
userData.uid = fromuid; | ||
Backend.parse(msg, userData, false, function(err, data) { | ||
var shout = {}; | ||
shout.user = data.userData; | ||
shout.user.isAdmin = data.isAdmin; | ||
shout.isNew = data.isNew; | ||
shout.content = data.content; | ||
shout.sid = sid; | ||
return callback(null, shout); | ||
}); | ||
getShouts([sid], false, function(err, shouts) { | ||
callback(err, shouts ? shouts[0] : null); | ||
}); | ||
@@ -148,6 +176,7 @@ }); | ||
}); | ||
}, | ||
pruneDeleted: function(uid, callback) { | ||
}; | ||
Backend.pruneDeleted = function(uid, callback) { | ||
User.isAdministrator(uid, function(err, isAdmin) { | ||
if (isAdmin === true) { | ||
if (isAdmin) { | ||
db.getListRange('shouts', 0, -1, function(err, sids) { | ||
@@ -160,12 +189,11 @@ if (err || !sids || !sids.length) { | ||
db.getObjectField('shout:' + sid, 'deleted', function(err, isDeleted) { | ||
if (isDeleted === '1') { | ||
if (parseInt(isDeleted, 10) === 1) { | ||
db.delete('shout:' + sid); | ||
db.listRemoveAll('shouts', sid); | ||
next() | ||
} | ||
next(null); | ||
next(); | ||
}); | ||
} | ||
async.map(sids, deleteShout, function(err) { | ||
async.eachSeries(sids, deleteShout, function(err) { | ||
if (err) { | ||
@@ -181,4 +209,5 @@ return callback(err, false); | ||
}); | ||
}, | ||
removeAll: function(uid, callback) { | ||
}; | ||
Backend.removeAll = function(uid, callback) { | ||
User.isAdministrator(uid, function(err, isAdmin) { | ||
@@ -210,12 +239,4 @@ if (isAdmin === true) { | ||
}); | ||
}, | ||
updateShoutTime: function(uid, callback) { | ||
db.sortedSetAdd('uid:' + uid + ':shouts', Date.now(), 0, function(err) { | ||
if (callback) { | ||
callback(err); | ||
} | ||
}); | ||
} | ||
} | ||
}; | ||
module.exports = Backend; | ||
})(module.exports); |
var NodeBB = module.require('./nodebb'), | ||
pjson = require('../package.json'), | ||
Meta = NodeBB.Meta, | ||
Settings = NodeBB.Settings, | ||
db = NodeBB.db; | ||
var Config = { | ||
plugin: { | ||
(function(Config) { | ||
Config.plugin = { | ||
name: 'Shoutbox', | ||
id: 'shoutbox', | ||
description: 'Shoutbox widget.', | ||
version: pjson.version, | ||
description: pjson.description, | ||
icon: 'fa-bullhorn', | ||
route: '/shoutbox' | ||
}, | ||
prefix: 'shoutbox:', | ||
keys: ['headerlink', 'shoutlimit', 'features'], | ||
defaults: { | ||
headerlink: '0', | ||
shoutlimit: 25, | ||
features: '{}' | ||
}, | ||
features: [{ | ||
name: 'Gists', | ||
id: 'gist', | ||
description: 'Easily create Gists', | ||
icon: 'fa-github-alt', | ||
button: 'Create Gist', | ||
enabled: true | ||
}, { | ||
name: 'Archive', | ||
id: 'archive', | ||
description: 'View older posts', | ||
icon: 'fa-archive', | ||
button: 'View Archive', | ||
enabled: true | ||
}, { | ||
name: 'Bugs', | ||
id: 'bug', | ||
description: 'Report bugs quickly', | ||
icon: 'fa-bug', | ||
button: 'Report Bug', | ||
enabled: true | ||
}], | ||
get: function(keys) { | ||
var get = function(key) { | ||
return Meta.config[Config.prefix + key] || Config.defaults[key]; | ||
}; | ||
var features = [ | ||
{ | ||
name: 'Gists', | ||
id: 'gist', | ||
description: 'Easily create Gists', | ||
icon: 'fa-github-alt', | ||
button: 'Create Gist', | ||
enabled: true | ||
}, | ||
{ | ||
name: 'Archive', | ||
id: 'archive', | ||
description: 'View older posts', | ||
icon: 'fa-archive', | ||
button: 'View Archive', | ||
enabled: true | ||
}, | ||
{ | ||
name: 'Bugs', | ||
id: 'bug', | ||
description: 'Report bugs quickly', | ||
icon: 'fa-bug', | ||
button: 'Report Bug', | ||
enabled: true | ||
} | ||
]; | ||
if (Array.isArray(keys)) { | ||
var result = {}; | ||
for(var i = 0, l = keys.length; i < l; i++) { | ||
if (Config.keys.indexOf(keys[i]) !== -1) { | ||
result[keys[i]] = get(keys[i]); | ||
} | ||
} | ||
return result; | ||
} else { | ||
return get(keys); | ||
var adminDefaults = { | ||
toggles: { | ||
headerLink: false, | ||
features: (function() { | ||
var defaults = {}; | ||
features.forEach(function(el) { | ||
defaults[el.id] = el.enabled; | ||
}); | ||
return defaults; | ||
})() | ||
}, | ||
limits: { | ||
shoutLimit: "25" | ||
} | ||
}, | ||
api: function(callback) { | ||
var config = Config.get(['features']), | ||
featureData = JSON.parse(config.features); | ||
config.features = Config.features.slice(0); | ||
if (featureData && Object.keys(featureData).length > 0) { | ||
config.features.map(function(item) { | ||
return featureData[item.id] ? item.enabled = featureData[item.id].enabled : item.enabled; | ||
}); | ||
}; | ||
var userDefaults = { | ||
// toggles: { | ||
// sound: true, | ||
// notification: true, | ||
// hide: false | ||
// }, | ||
// muted: '', | ||
'shoutbox:toggles:sound': true, | ||
'shoutbox:toggles:notification': true, | ||
'shoutbox:toggles:hide': false, | ||
'shoutbox:muted': '' | ||
}; | ||
Config.global = new Settings(Config.plugin.id, Config.plugin.version, adminDefaults); | ||
Config.adminSockets = { | ||
sync: function() { | ||
Config.global.sync(); | ||
}, | ||
getDefaults: function(socket, data, callback) { | ||
callback(null, Config.global.createDefaultWrapper()); | ||
} | ||
callback(config); | ||
} | ||
}; | ||
}; | ||
Config.settings = { | ||
keys: ['sound', 'notification', 'hide'], | ||
defaults: { | ||
sound: 1, | ||
notification: 1, | ||
hide: 0 | ||
}, | ||
get: function(data, callback) { | ||
db.getObjectFields('user:' + data.uid + ':settings', Config.settings.keys.map(function(e) { | ||
return Config.prefix + e; | ||
}), function(err, result) { | ||
//Config.user = new Settings(Config.plugin.id + 'User', Config.plugin.version, userDefaults); | ||
Config.user = {}; | ||
Config.user.get = function(data, callback) { | ||
db.getObjectFields('user:' + data.uid + ':settings', Object.keys(userDefaults), function(err, result) { | ||
for (var k in result) { | ||
if (result.hasOwnProperty(k) && k != '_key') { | ||
data.settings[k] = result[k] !== null ? result[k] : Config.settings.defaults[k.split(':')[1]]; | ||
data.settings[k] = result[k] !== null ? result[k] : userDefaults[k]; | ||
} | ||
} | ||
callback(null, data); | ||
}); | ||
}, | ||
save: function(data, callback) { | ||
}; | ||
Config.user.save = function(data, callback) { | ||
if (data.uid) { | ||
var s; | ||
for (var k in Config.settings.keys) { | ||
if (Config.settings.keys.hasOwnProperty(k)) { | ||
s = Config.prefix + Config.settings.keys[k]; | ||
if (data.settings[s] !== undefined) { | ||
db.setObjectField('user:' + data.uid + ':settings', s, data.settings[s]); | ||
} | ||
var keys = Object.keys(userDefaults), cur; | ||
for (var i = 0, l = keys.length; i < l; i++) { | ||
cur = keys[i]; | ||
if (data.settings[cur] !== undefined) { | ||
db.setObjectField('user:' + data.uid + ':settings', cur, data.settings[cur]); | ||
} | ||
@@ -107,5 +112,43 @@ } | ||
} | ||
} | ||
} | ||
}; | ||
module.exports = Config; | ||
Config.userSockets = { | ||
getSettings: function(socket, data, callback) { | ||
if (socket.uid === 0) { | ||
return; | ||
} | ||
Config.user.get({ uid: socket.uid, settings: {} }, function(err, result) { | ||
var settings = result.settings; | ||
settings['shoutbox:shoutLimit'] = parseInt(Config.global.get('limits.shoutLimit'), 10); | ||
callback(null, { | ||
settings: settings | ||
}); | ||
}); | ||
}, | ||
saveSettings: function(socket, data, callback) { | ||
if (!data || !data.key || !socket.uid) { | ||
return callback(null, false); | ||
} | ||
var setting = {}; | ||
setting[data.key] = data.value; | ||
Config.user.save({ uid: socket.uid, settings: setting}, callback); | ||
} | ||
}; | ||
Config.getTemplateData = function(callback) { | ||
var featureConfig = Config.global.get('toggles.features'), | ||
data = {}; | ||
data.features = features.slice(0).map(function(item) { | ||
item.enabled = featureConfig[item.id]; | ||
return item; | ||
}); | ||
callback(data); | ||
}; | ||
})(module.exports); |
@@ -1,8 +0,12 @@ | ||
module.exports = { | ||
Meta: module.parent.parent.require('./meta'), | ||
User: module.parent.parent.require('./user'), | ||
Plugins: module.parent.parent.require('./plugins'), | ||
SocketIndex: module.parent.parent.require('./socket.io/index'), | ||
ModulesSockets: module.parent.parent.require('./socket.io/modules'), | ||
db: module.parent.parent.require('./database') | ||
} | ||
(function(NodeBB) { | ||
module.exports = { | ||
Settings: NodeBB.require('./settings'), | ||
Meta: NodeBB.require('./meta'), | ||
User: NodeBB.require('./user'), | ||
Plugins: NodeBB.require('./plugins'), | ||
SocketIndex: NodeBB.require('./socket.io/index'), | ||
SocketPlugins: NodeBB.require('./socket.io/plugins'), | ||
SocketAdmin: NodeBB.require('./socket.io/admin').plugins, | ||
db: NodeBB.require('./database') | ||
} | ||
})(module.parent.parent); |
@@ -6,133 +6,146 @@ var S = require('string'), | ||
Backend = require('./backend'), | ||
Commands = require('./commands'), | ||
User = NodeBB.User, | ||
SocketIndex = NodeBB.SocketIndex; | ||
//todo clean this up and improve | ||
var Sockets = { | ||
get: function(socket, data, callback) { | ||
var start, end; | ||
if (data && (data.start && data.end)) { | ||
start = parseInt(data.start, 10); | ||
end = parseInt(data.end, 10); | ||
} else { | ||
start = -(parseInt(Config.get('shoutlimit'), 10) - 1); | ||
end = -1; | ||
} | ||
if (socket.uid) { | ||
Backend.getShouts(start, end, function(err, messages) { | ||
if (err) | ||
return callback(null, []); | ||
(function(Sockets) { | ||
callback(null, messages); | ||
}); | ||
} else { | ||
callback(null, []); | ||
} | ||
}, | ||
send: function(socket, data, callback) { | ||
if(!data || socket.uid === 0) { | ||
return callback(new Error('invalid-data')); | ||
} | ||
var uidSocketIndex = {}, | ||
handlers = { | ||
get: function(socket, data, callback) { | ||
var start, end; | ||
var msg = S(data.message).stripTags().trim().s; | ||
if (msg.length) { | ||
User.getMultipleUserFields([socket.uid], ['username', 'userslug', 'picture', 'status'], function(err, userData) { | ||
if(err) { | ||
return; | ||
} | ||
if (data && data.start) { | ||
start = parseInt(data.start, 10); | ||
end = start + parseInt(Config.global.get('limits.shoutLimit'), 10); | ||
} else { | ||
start = -(parseInt(Config.global.get('limits.shoutLimit'), 10)); | ||
end = -1; | ||
} | ||
userData = userData[0]; | ||
userData.uid = socket.uid; | ||
Backend.parse(msg, userData, true, function(err, data) { | ||
Backend.addShout(socket.uid, msg, function(err, message) { | ||
message.user = data.userData; | ||
message.user.isAdmin = data.isAdmin; | ||
message.isNew = data.isNew; | ||
message.content = data.content; | ||
SocketIndex.server.sockets.emit('event:shoutbox.receive', message); | ||
}); | ||
if (socket.uid) { | ||
updateUidSocketIndex(socket); | ||
Backend.getShouts(start, end, function(err, messages) { | ||
if (err) { | ||
return callback(null, []); | ||
} | ||
callback(null, messages); | ||
}); | ||
}); | ||
} | ||
}, | ||
remove: function(socket, data, callback) { | ||
if (data && data.sid) { | ||
Backend.removeShout(data.sid.toString(), socket.uid, function(err, result) { | ||
if (result === true) { | ||
SocketIndex.server.sockets.emit('event:shoutbox.delete', { | ||
sid: data.sid | ||
}); | ||
} | ||
callback(err, result); | ||
}); | ||
} | ||
}, | ||
edit: function(socket, data, callback) { | ||
if (data && data.sid) { | ||
var msg = S(data.edited).stripTags().s; | ||
Backend.editShout(data.sid.toString(), msg, socket.uid, function(err, result) { | ||
if (err === null) { | ||
} else { | ||
callback(null, []); | ||
} | ||
}, | ||
send: function(socket, data, callback) { | ||
if (!data || socket.uid === 0) { | ||
return callback(new Error('invalid-data')); | ||
} | ||
updateUidSocketIndex(socket); | ||
var msg = S(data.message).stripTags().trim().s; | ||
if (msg.length) { | ||
Backend.addShout(socket.uid, msg, function(err, shout) { | ||
SocketIndex.server.sockets.emit('event:shoutbox.receive', shout); | ||
callback(null, true); | ||
}); | ||
} | ||
}, | ||
remove: function(socket, data, callback) { | ||
if (data && data.sid) { | ||
Backend.removeShout(data.sid, socket.uid, function(err, result) { | ||
if (result === true) { | ||
SocketIndex.server.sockets.emit('event:shoutbox.delete', { | ||
sid: data.sid | ||
}); | ||
} | ||
callback(err, result); | ||
}); | ||
} | ||
}, | ||
edit: function(socket, data, callback) { | ||
if (data && data.sid) { | ||
var msg = S(data.edited).stripTags().s; | ||
Backend.editShout(data.sid, msg, socket.uid, function(err, result) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
SocketIndex.server.sockets.emit('event:shoutbox.edit', result); | ||
result = true; | ||
} | ||
callback(err, result); | ||
}); | ||
} | ||
}, | ||
removeAll: function(socket, data, callback) { | ||
if(!data) { | ||
return callback(new Error('invalid-data')); | ||
} | ||
if (data.which === 'deleted') { | ||
return Backend.pruneDeleted(socket.uid, callback); | ||
} else if (data.which === 'all') { | ||
return Backend.removeAll(socket.uid, callback); | ||
} | ||
return callback(null, false); | ||
}, | ||
getUsers: function(socket, data, callback){ | ||
var users = SocketIndex.getConnectedClients(); | ||
User.getMultipleUserFields(users, ['username'], function(err, usersData) { | ||
if(err) { | ||
return callback(null, []); | ||
return callback(err, true); | ||
}); | ||
} | ||
return callback(null, usersData); | ||
}); | ||
}, | ||
getSettings: function(socket, data, callback) { | ||
if (socket.uid === 0) { | ||
return; | ||
} | ||
Config.settings.get({ uid: socket.uid, settings: {} }, function(err, result) { | ||
var settings = {}; | ||
for (var i = 0, l = Config.settings.keys.length; i < l; i++) { | ||
settings[Config.settings.keys[i]] = result.settings[Config.prefix + Config.settings.keys[i]]; | ||
}, | ||
removeAll: function(socket, data, callback) { | ||
if(!data) { | ||
return callback(new Error('invalid-data')); | ||
} | ||
callback(null, { | ||
settings: settings, | ||
shoutLimit: parseInt(Config.get('shoutlimit'), 10) | ||
}); | ||
}); | ||
}, | ||
saveSetting: function(socket, data, callback) { | ||
if (!data || !data.key || !socket.uid) { | ||
if (data.which === 'deleted') { | ||
return Backend.pruneDeleted(socket.uid, callback); | ||
} else if (data.which === 'all') { | ||
return Backend.removeAll(socket.uid, callback); | ||
} | ||
return callback(null, false); | ||
}, | ||
getOriginalShout: function(socket, data, callback) { | ||
if (data.sid && socket.uid !== 0) { | ||
Backend.getRawShout(data.sid, function(err, shout) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
return callback(null, shout.content); | ||
}); | ||
} | ||
}, | ||
notifyStartTyping: function(socket, data, callback) { | ||
if (!socket.uid) { | ||
return; | ||
} | ||
var uid = socket.uid; | ||
SocketIndex.server.sockets.emit('event:shoutbox.startTyping', { uid: uid }); | ||
if (socket.listeners('disconnect').length === 0) { | ||
socket.on('disconnect', function() { | ||
Sockets.notifyStopTyping(socket, data, callback); | ||
}); | ||
} | ||
}, | ||
notifyStopTyping: function(socket, data, callback) { | ||
if (!socket.uid) { | ||
return; | ||
} | ||
var uid = socket.uid; | ||
SocketIndex.server.sockets.emit('event:shoutbox.stopTyping', { uid: uid }); | ||
}, | ||
getSettings: Config.userSockets.getSettings, | ||
saveSetting: Config.userSockets.saveSettings | ||
}; | ||
function updateUidSocketIndex(socket) { | ||
if (!socket.isBot) { | ||
uidSocketIndex[socket.uid] = socket; | ||
if (socket.listeners('disconnect').length === 0) { | ||
socket.on('disconnect', function() { | ||
delete uidSocketIndex[socket.uid]; | ||
}); | ||
} | ||
} | ||
var setting = {}; | ||
setting[Config.prefix + data.key] = data.value; | ||
Config.settings.save({ uid: socket.uid, settings: setting}, callback); | ||
}, | ||
getOriginalShout: function(socket, data, callback) { | ||
if (data.sid && socket.uid !== 0) { | ||
Backend.getShout(data.sid, function(err, shout) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
return callback(null, shout.content); | ||
}); | ||
} | ||
for (var s in Commands.sockets) { | ||
if (Commands.sockets.hasOwnProperty(s)) { | ||
handlers[s] = Commands.sockets[s]; | ||
} | ||
} | ||
} | ||
module.exports = Sockets; | ||
Sockets.events = handlers; | ||
Sockets.uidSocketIndex = uidSocketIndex; | ||
})(module.exports); |
@@ -1,13 +0,8 @@ | ||
var fs = require('fs'), | ||
path = require('path'), | ||
NodeBB = require('./lib/nodebb'), | ||
var NodeBB = require('./lib/nodebb'), | ||
Config = require('./lib/config'), | ||
Sockets = require('./lib/sockets'), | ||
ModulesSockets = NodeBB.ModulesSockets, | ||
SocketPlugins = NodeBB.SocketPlugins, | ||
SocketAdmin = NodeBB.SocketAdmin, | ||
User = NodeBB.User, | ||
db = NodeBB.db, | ||
app; | ||
@@ -17,25 +12,32 @@ | ||
Shoutbox.init = { | ||
load: function(expressApp, middleware, controllers) { | ||
Shoutbox.register = { | ||
load: function(expressApp, middleware, controllers, callback) { | ||
app = expressApp; | ||
function renderGlobal(req, res, next) { | ||
Config.api(function(data) { | ||
res.render('shoutbox', data); | ||
Config.getTemplateData(function(data) { | ||
res.render(Config.plugin.id, data); | ||
}); | ||
} | ||
function renderAdmin(req, res, next) { | ||
Config.api(function(data) { | ||
res.render('shoutbox/admin', data); | ||
Config.getTemplateData(function(data) { | ||
res.render('admin/' + Config.plugin.id, data); | ||
}); | ||
} | ||
app.get('/shoutbox', middleware.buildHeader, renderGlobal); | ||
app.get('/api/shoutbox', renderGlobal); | ||
app.get('/admin/shoutbox', middleware.admin.buildHeader, renderAdmin); | ||
app.get('/api/admin/shoutbox', renderAdmin); | ||
ModulesSockets.shoutbox = Sockets; | ||
app.get(Config.plugin.route, middleware.buildHeader, renderGlobal); | ||
app.get('/api' + Config.plugin.route, renderGlobal); | ||
app.get('/admin' + Config.plugin.route, middleware.admin.buildHeader, renderAdmin); | ||
app.get('/api/admin' + Config.plugin.route, renderAdmin); | ||
SocketPlugins[Config.plugin.id] = Sockets.events; | ||
SocketAdmin[Config.plugin.id] = Config.adminSockets; | ||
callback(expressApp, middleware, controllers); | ||
}, | ||
global: { | ||
addNavigation: function(custom_header, callback) { | ||
if (Config.get('headerlink') === '1') { | ||
if (Config.global.get('toggles.headerLink')) { | ||
custom_header.navigation.push({ | ||
@@ -48,2 +50,3 @@ class: '', | ||
} | ||
callback(null, custom_header); | ||
@@ -63,3 +66,3 @@ } | ||
} | ||
} | ||
}; | ||
@@ -74,25 +77,29 @@ Shoutbox.widget = { | ||
}); | ||
callback(null, widgets); | ||
}, | ||
render: function(widget, callback) { | ||
if (widget.uid === 0) { | ||
return callback(); | ||
} | ||
//Remove any container | ||
widget.data.container = ''; | ||
if (widget.uid !== 0) { | ||
//Currently doing this on the server -- still debating what's better | ||
Config.settings.get({ uid: widget.uid, settings: {} }, function(err, result) { | ||
Config.api(function(data) { | ||
data.hiddenStyle = ''; | ||
if (result.settings[Config.prefix + 'hide'] == 1) { | ||
data.hiddenStyle = 'display: none;'; | ||
} | ||
app.render('shoutbox', data, callback); | ||
}); | ||
//Currently doing this on the server -- still debating what's better | ||
Config.user.get({ uid: widget.uid, settings: {} }, function(err, result) { | ||
Config.getTemplateData(function(data) { | ||
data.hiddenStyle = ''; | ||
if (parseInt(result.settings['shoutbox:toggles:hide'], 10) == 1) { | ||
data.hiddenStyle = 'display: none;'; | ||
} | ||
app.render('shoutbox/panel', data, callback); | ||
}); | ||
// Client or server? | ||
}); | ||
// Client or server? | ||
// Config.api(function(data) { | ||
// app.render('shoutbox', data, callback); | ||
// }); | ||
} | ||
} | ||
} | ||
}; | ||
@@ -108,12 +115,19 @@ Shoutbox.settings = { | ||
}); | ||
}, | ||
getUserSettings: function(data, callback) { | ||
Config.settings.get(data, callback); | ||
Config.user.get(data, callback); | ||
}, | ||
saveUserSettings: function(data) { | ||
Config.settings.save(data); | ||
Config.user.save(data); | ||
} | ||
} | ||
}; | ||
Shoutbox.sounds = { | ||
getSounds: function(sounds, callback) { | ||
sounds.push(__dirname + '/public/sounds/shoutbox-notification.mp3'); | ||
sounds.push(__dirname + '/public/sounds/shoutbox-wobblysausage.mp3'); | ||
callback(null, sounds); | ||
} | ||
}; | ||
module.exports = Shoutbox; |
{ | ||
"name": "nodebb-plugin-shoutbox", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "NodeBB Shoutbox Plugin", | ||
@@ -5,0 +5,0 @@ "main": "library.js", |
@@ -8,8 +8,11 @@ { | ||
"hooks": [ | ||
{ "hook": "action:app.load", "method": "init.load" }, | ||
{ "hook": "filter:admin.header.build", "method": "init.admin.addNavigation" }, | ||
{ "hook": "filter:header.build", "method": "init.global.addNavigation" }, | ||
{ "hook": "static:app.load", "method": "register.load" }, | ||
{ "hook": "filter:admin.header.build", "method": "register.admin.addNavigation" }, | ||
{ "hook": "filter:header.build", "method": "register.global.addNavigation" }, | ||
{ "hook": "filter:user.settings", "method": "settings.addUserSettings" }, | ||
{ "hook": "filter:user.getSettings", "method": "settings.getUserSettings" }, | ||
{ "hook": "action:user.saveSettings", "method": "settings.saveUserSettings" }, | ||
{ "hook": "filter:sounds.get", "method": "sounds.getSounds" }, | ||
{ "hook": "filter:widgets.getWidgets", "method": "widget.define" }, | ||
@@ -25,6 +28,7 @@ { "hook": "filter:widget.render:shoutbox", "method": "widget.render" } | ||
"scripts": [ | ||
"public/js/loader.js" | ||
"public/js/loader.js", | ||
"public/js/lib/" | ||
], | ||
"templates": "./templates", | ||
"minver": "0.4.0" | ||
"minver": "0.5.0" | ||
} |
(function() { | ||
var settings, wrapper, saveInterval; | ||
$(document).ready(function() { | ||
require(['forum/admin/settings'], function(Settings) { | ||
Settings.prepare(function() { | ||
prepareFeatures(); | ||
require(['settings'], function(_settings) { | ||
settings = _settings; | ||
wrapper = $('#shoutboxAdminForm'); | ||
settings.sync('shoutbox', wrapper, function() { | ||
prepareFeatures(settings.get().toggles.features); | ||
}); | ||
$('#save').click(function(event) { | ||
event.preventDefault(); | ||
save(); | ||
}); | ||
$('#reset').click(function(event) { | ||
event.preventDefault(); | ||
reset(); | ||
}); | ||
prepareButtons(); | ||
wrapper.on('change', function(event) { | ||
save(); | ||
}); | ||
}); | ||
prepareButtons(); | ||
}); | ||
function prepareFeatures() { | ||
function updateSettings() { | ||
var features = {}; | ||
$('[data-feature]').each(function() { | ||
var feature = $(this).data('feature'); | ||
features[feature] = { | ||
feature: feature, | ||
enabled: $(this).find('.fa').hasClass('fa-check-circle') | ||
}; | ||
function save() { | ||
clearTimeout(saveInterval); | ||
saveInterval = setTimeout(function() { | ||
settings.persist('shoutbox', wrapper, function() { | ||
socket.emit('admin.plugins.shoutbox.sync'); | ||
}); | ||
$('#features-settings').val(JSON.stringify(features)); | ||
} | ||
}, 1000); | ||
} | ||
function reset() { | ||
bootbox.confirm('Are you sure you wish to reset the settings?', function(sure) { | ||
if (sure) { | ||
socket.emit('admin.plugins.shoutbox.getDefaults', null, function (err, data) { | ||
settings.set('shoutbox', data, wrapper, function(){ | ||
socket.emit('admin.plugins.shoutbox.sync'); | ||
}); | ||
}); | ||
} | ||
}); | ||
} | ||
function prepareFeatures(featureSettings) { | ||
function on(feature) { | ||
@@ -28,3 +59,6 @@ var el = $('[data-feature="' + feature + '"]'); | ||
el.removeClass('disabled'); | ||
el.find('input:checkbox').prop('checked', true); | ||
} | ||
function off(feature) { | ||
@@ -34,2 +68,4 @@ var el = $('[data-feature="' + feature + '"]'); | ||
el.addClass('disabled'); | ||
el.find('input:checkbox').prop('checked', false); | ||
} | ||
@@ -44,3 +80,3 @@ | ||
} | ||
updateSettings(); | ||
save(); | ||
} | ||
@@ -60,11 +96,11 @@ | ||
var saved = JSON.parse($('#features-settings').val()); | ||
for (var feature in saved) { | ||
if (saved.hasOwnProperty(feature)) { | ||
if (!saved[feature].enabled) { | ||
for (var feature in featureSettings) { | ||
if (featureSettings.hasOwnProperty(feature)) { | ||
if (!featureSettings[feature]) { | ||
off(feature); | ||
} else { | ||
on(feature); | ||
} | ||
} | ||
} | ||
updateSettings(); | ||
} | ||
@@ -76,3 +112,3 @@ | ||
if (confirm) { | ||
socket.emit('modules.shoutbox.removeAll', {'which':'deleted'}, function(err, result) { | ||
socket.emit('plugins.shoutbox.removeAll', {'which':'deleted'}, function(err, result) { | ||
if(err) { | ||
@@ -91,3 +127,3 @@ return app.alertError(err.message); | ||
if (confirm) { | ||
socket.emit('modules.shoutbox.removeAll', {'which':'all'}, function(err, result) { | ||
socket.emit('plugins.shoutbox.removeAll', {'which':'all'}, function(err, result) { | ||
if(err) { | ||
@@ -94,0 +130,0 @@ return app.alertError(err.message); |
@@ -1,285 +0,16 @@ | ||
define(['string'], function(S) { | ||
var sb; | ||
(function(Shoutbox) { | ||
var actions = []; | ||
var Actions = { | ||
send: { | ||
register: function(shoutBox) { | ||
var sendMessage = this.handle; | ||
shoutBox.find('#shoutbox-message-input').off('keypress').on('keypress', function(e) { | ||
if(e.which === 13 && !e.shiftKey) { | ||
sendMessage(shoutBox); | ||
} | ||
}); | ||
shoutBox.find('#shoutbox-message-send-btn').off('click').on('click', function(e){ | ||
sendMessage(shoutBox); | ||
return false; | ||
}); | ||
}, | ||
handle: function(shoutBox) { | ||
var msg = S(shoutBox.find('#shoutbox-message-input').val()).stripTags().trim().s; | ||
if(msg.length) { | ||
socket.emit(sb.config.sockets.send, { message:msg }); | ||
} | ||
shoutBox.find('#shoutbox-message-input').val(''); | ||
} | ||
Shoutbox.actions = { | ||
register: function(obj) { | ||
actions.push(obj); | ||
}, | ||
delete: { | ||
register: function(shoutBox) { | ||
shoutBox.off('click', '.shoutbox-shout-option-close').on('click', '.shoutbox-shout-option-close', this.handle); | ||
}, | ||
handle: function(e) { | ||
var sid = $(e.currentTarget).parents('[data-sid]').data('sid'); | ||
socket.emit(sb.config.sockets.remove, { sid: sid }, function (err, result) { | ||
if (result === true) { | ||
app.alertSuccess('Successfully deleted shout!'); | ||
} else if (err) { | ||
app.alertError('Error deleting shout: ' + err.message, 3000); | ||
} | ||
}); | ||
return false; | ||
} | ||
}, | ||
edit: { | ||
register: function(shoutBox) { | ||
var handle = this.handle; | ||
shoutBox.off('click', '.shoutbox-shout-option-edit').on('click', '.shoutbox-shout-option-edit', function(e) { | ||
handle(shoutBox, $(e.currentTarget).parents('[data-sid]').data('sid')); | ||
}); | ||
shoutBox.off('dblclick', '[data-sid]').on('dblclick', '[data-sid]', function(e) { | ||
handle(shoutBox, $(e.currentTarget).data('sid')); | ||
}); | ||
shoutBox.find('#shoutbox-message-input').off('keyup').on('keyup', function(e) { | ||
if(e.which === 38) { | ||
handle(shoutBox, shoutBox.find('[data-uid="' + app.uid + '"] [data-sid]:last').data('sid')); | ||
} | ||
}); | ||
}, | ||
handle: function(shoutBox, sid) { | ||
var shout = shoutBox.find('[data-sid="' + sid + '"]'); | ||
if (shout.parents('[data-uid]').data('uid') === app.uid || app.isAdmin) { | ||
Actions.edit.editing = sid; | ||
socket.emit(sb.config.sockets.getOriginalShout, { sid: sid }, function(err, orig) { | ||
shoutBox.find('#shoutbox-message-send-btn').off('click').on('click', function(e){ | ||
edit(orig); | ||
}).text('Edit'); | ||
shoutBox.find('#shoutbox-message-input').off('keyup').off('keypress').on('keypress', function(e) { | ||
if (e.which === 13 && !e.shiftKey) { | ||
edit(orig); | ||
} | ||
}).on('keyup', function(e) { | ||
if (e.currentTarget.value.length === 0) { | ||
Actions.edit.finish(shoutBox); | ||
} | ||
}).val(orig).focus().putCursorAtEnd().parent().addClass('has-warning'); | ||
}); | ||
initialize: function(shoutPanel) { | ||
for (var a in actions) { | ||
if (actions.hasOwnProperty(a)) { | ||
actions[a].register(shoutPanel); | ||
} | ||
function edit(orig) { | ||
var msg = S(shoutBox.find('#shoutbox-message-input').val()).stripTags().s; | ||
if (msg === orig || msg === '' || msg === null) { | ||
return Actions.edit.finish(shoutBox); | ||
} | ||
socket.emit(sb.config.sockets.edit, { sid: sid, edited: msg }, function (err, result) { | ||
if (result === true) { | ||
app.alertSuccess('Successfully edited shout!'); | ||
} else if (err) { | ||
app.alertError('Error editing shout: ' + err.message, 3000); | ||
} | ||
Actions.edit.finish(shoutBox); | ||
}); | ||
} | ||
return false; | ||
}, | ||
finish: function(shoutBox) { | ||
var parent = shoutBox.find('#shoutbox-message-input').parent(); | ||
parent.removeClass('has-warning').find('#shoutbox-message-send-btn').removeClass('hide'); | ||
parent.find('#shoutbox-message-send-btn').text('Send'); | ||
parent.find('#shoutbox-message-input').val(''); | ||
Actions.send.register(shoutBox); | ||
Actions.edit.register(shoutBox); | ||
Actions.edit.editing = 0; | ||
}, | ||
editing: 0 | ||
}, | ||
gist: { | ||
register: function(shoutBox) { | ||
var show = this.handle.show, | ||
create = this.handle.create, | ||
gistModal = $('#shoutbox-modal-gist'); | ||
shoutBox.find('#shoutbox-button-gist').off('click').on('click', function(e) { | ||
show(gistModal); | ||
}); | ||
gistModal.find('#shoutbox-button-create-gist-submit').off('click').on('click', function(e) { | ||
create(gistModal.find('textarea').val(), gistModal); | ||
}); | ||
}, | ||
handle: { | ||
show: function(gistModal) { | ||
gistModal.modal('show'); | ||
}, | ||
'create': function(code, gistModal) { | ||
if (app.uid === null) { | ||
gistModal.modal('hide'); | ||
app.alertError('Only registered users can create Gists!', 3000); | ||
return; | ||
} | ||
var json = { | ||
"description": "Gist created from BitBangers shoutbox", | ||
"public": true, | ||
"files": { | ||
"file1.txt": { | ||
"content": code | ||
} | ||
} | ||
} | ||
$.post('https://api.github.com/gists', JSON.stringify(json), function(data) { | ||
gistModal.modal('hide'); | ||
var input = sb.base.getShoutPanel().find('#shoutbox-message-input'); | ||
var link = data.html_url; | ||
if (input.val().length > 0) { | ||
link = ' ' + link; | ||
} | ||
input.val(input.val() + link); | ||
app.alertSuccess('Successfully created Gist!', 3000); | ||
gistModal.find('textarea').val(''); | ||
}).fail(function(data) { | ||
gistModal.modal('hide'); | ||
app.alertError('Error while creating Gist, try again later!', 3000); | ||
}); | ||
} | ||
} | ||
}, | ||
archive: { | ||
register: function(shoutBox) { | ||
var handle = this.handle, | ||
archiveModal = $('#shoutbox-archive-modal'); | ||
shoutBox.find('#shoutbox-button-archive').off('click').on('click', function(e) { | ||
handle.show(archiveModal, handle); | ||
}); | ||
archiveModal.find('#shoutbox-button-archive-prev').off('click').on('click', function(e) { | ||
handle.prev(archiveModal, handle); | ||
}); | ||
archiveModal.find('#shoutbox-button-archive-next').off('click').on('click', function(e) { | ||
handle.next(archiveModal, handle); | ||
}); | ||
}, | ||
handle: { | ||
show: function(archiveModal, handle) { | ||
archiveModal.modal('show'); | ||
if (!archiveModal.data('start')) { | ||
archiveModal.data('start', (-(sb.config.vars.shoutLimit - 1)).toString()); | ||
archiveModal.data('end', '-1'); | ||
} | ||
handle.get(archiveModal, handle); | ||
}, | ||
prev: function(archiveModal, handle) { | ||
var start = parseInt(archiveModal.data('start'), 10) - sb.config.vars.shoutLimit, | ||
end = parseInt(archiveModal.data('end'), 10) - sb.config.vars.shoutLimit; | ||
if (Math.abs(start) < (parseInt(sb.config.vars.lastSid, 10) + sb.config.vars.shoutLimit)) { | ||
archiveModal.data('start', start); | ||
archiveModal.data('end', end); | ||
handle.get(archiveModal, handle); | ||
} | ||
}, | ||
next: function(archiveModal, handle) { | ||
var start = parseInt(archiveModal.data('start'), 10) + sb.config.vars.shoutLimit, | ||
end = parseInt(archiveModal.data('end'), 10) + sb.config.vars.shoutLimit, | ||
startLimit = -(sb.config.vars.shoutLimit - 1); | ||
if (start <= startLimit && end < 0) { | ||
archiveModal.data('start', start); | ||
archiveModal.data('end', end); | ||
handle.get(archiveModal, handle); | ||
} | ||
}, | ||
get: function(archiveModal, handle) { | ||
archiveModal.find('#shoutbox-archive-content').html(''); | ||
var start = archiveModal.data('start'), | ||
end = archiveModal.data('end'); | ||
socket.emit(sb.config.sockets.get, { start: start, end: end }, function(err, shouts) { | ||
for(var i = 0; i < shouts.length; i++) { | ||
handle.addShout(archiveModal, shouts[i]); | ||
} | ||
archiveModal.find('.shoutbox-shout-options').remove(); | ||
}); | ||
}, | ||
addShout: function(archiveModal, shout) { | ||
if (shout && shout.sid) { | ||
var archiveContent = archiveModal.find('#shoutbox-archive-content'); | ||
if (parseInt(shout.fromuid, 10) === archiveContent.find('[data-uid]:last').data('uid')) { | ||
archiveContent.find('[data-sid]:last').after(sb.utils.parseShout(shout, true)); | ||
} else { | ||
archiveContent.append(sb.utils.parseShout(shout)); | ||
} | ||
sb.base.scrollToBottom(archiveContent); | ||
} | ||
} | ||
} | ||
}, | ||
bug: { | ||
register: function(shoutBox) { | ||
shoutBox.find('#shoutbox-button-bug').off('click').on('click', this.handle); | ||
}, | ||
handle: function(e) { | ||
window.open('https://github.com/Schamper/nodebb-plugin-shoutbox/issues/new', '_blank').focus(); | ||
} | ||
}, | ||
settings: { | ||
register: function(shoutBox) { | ||
shoutBox.off('click', '#shoutbox-settings-menu a').on('click', '#shoutbox-settings-menu a', this.handle); | ||
}, | ||
handle: function(e) { | ||
var el = $(e.currentTarget), | ||
statusEl = el.find('span'), | ||
key = el.attr('id').split('shoutbox-settings-')[1], | ||
status = statusEl.hasClass('fa-check'); | ||
if (status) { | ||
statusEl.removeClass('fa-check').addClass('fa-times'); | ||
status = 0; | ||
} else { | ||
statusEl.removeClass('fa-times').addClass('fa-check'); | ||
status = 1; | ||
} | ||
sb.config.settings[key] = !status; | ||
socket.emit(sb.config.sockets.saveSettings, { key: key, value: status }, function(err, result) { | ||
if (err || result === false) { | ||
app.alertError('Error saving settings!'); | ||
} | ||
}); | ||
return false; | ||
} | ||
}, | ||
hide: { | ||
register: function(shoutBox) { | ||
shoutBox.off('click', '#shoutbox-settings-hide').on('click', '#shoutbox-settings-hide', this.handle); | ||
}, | ||
handle: function(e) { | ||
var el = $(e.currentTarget).find('span'), | ||
body = sb.base.getShoutPanel().find('.panel-body'); | ||
if (el.hasClass('fa-arrow-up')) { | ||
body.slideUp(); | ||
el.removeClass('fa-arrow-up').addClass('fa-arrow-down'); | ||
sb.config.settings['hide'] = true; | ||
} else { | ||
body.slideDown(); | ||
el.removeClass('fa-arrow-down').addClass('fa-arrow-up'); | ||
sb.config.settings['hide'] = false; | ||
} | ||
socket.emit(sb.config.sockets.saveSettings, { key: 'hide', value: sb.config.settings['hide'] }); | ||
} | ||
} | ||
}; | ||
return function(Shoutbox) { | ||
Shoutbox.actions = Actions; | ||
sb = Shoutbox; | ||
}; | ||
}); | ||
})(window.Shoutbox); |
@@ -1,59 +0,86 @@ | ||
define(function() { | ||
var sb; | ||
(function(Shoutbox) { | ||
var Base = { | ||
initialize: function(url, shoutPanel) { | ||
Base.vars.shoutPanel = shoutPanel; | ||
if (!Shoutbox.utils.isAnon()) { | ||
Shoutbox.utils.initialize(shoutPanel, function() { | ||
Base.getShouts(shoutPanel); | ||
var Base = { | ||
load: function() { | ||
sb.utils.checkAnon(function(isAnon) { | ||
if(!isAnon) { | ||
sb.utils.prepareShoutbox(Base); | ||
} | ||
}); | ||
//Add mentions autofill | ||
if (typeof Mentions !== 'undefined' && typeof Mentions.addAutofill !== 'undefined') { | ||
Mentions.addAutofill(shoutPanel.find('#shoutbox-message-input'), []); | ||
} | ||
//Add emoji autocomplete | ||
function addEmoji(emoji) { | ||
emoji.addCompletion(shoutPanel.find('#shoutbox-message-input')); | ||
} | ||
if (typeof emojiExtended !== 'undefined') { | ||
addEmoji(emojiExtended); | ||
} else { | ||
$(window).one('emoji-extended:initialized', addEmoji); | ||
} | ||
if (url === 'shoutbox') { | ||
Shoutbox.base.showUserPanel(); | ||
} | ||
}); | ||
} | ||
}, | ||
addShout: function(shoutBox, shout) { | ||
addShout: function(shout, shoutPanel) { | ||
if (shout && shout.sid) { | ||
var shoutContent = shoutBox.find('#shoutbox-content'); | ||
if (shoutContent.find('div[class="shoutbox-shout-container"]').length === 0) { | ||
shoutContent.html(''); | ||
} | ||
var shoutContent = shoutPanel.find('#shoutbox-content'); | ||
// add timeString to shout | ||
// jQuery.timeago only works properly with ISO timestamps | ||
shout.timeString = (new Date( parseInt( shout.timestamp, 10 ) ).toISOString() ); | ||
if (parseInt(shout.fromuid, 10) === shoutContent.find('[data-uid]:last').data('uid')) { | ||
shoutContent.find('[data-sid]:last').after(sb.utils.parseShout(shout, true)); | ||
shoutContent.find('[data-sid]:last').after(Shoutbox.utils.parseShout(shout, true)); | ||
} else { | ||
shoutContent.append(sb.utils.parseShout(shout)); | ||
shoutContent.append(Shoutbox.utils.parseShout(shout)); | ||
} | ||
Base.scrollToBottom(shoutContent); | ||
sb.config.vars.lastSid = shout.sid; | ||
// We need to update the timestring on every new activity. Shout.tpl is only parsed for the shout of a | ||
// chain breaking user, after that only text.tpl is parsed. | ||
var lastChainTimestamp = shoutContent.find('[data-uid="' + shout.fromuid + '"] span.timeago:last'); | ||
lastChainTimestamp.attr('title', shout.timeString); | ||
// execute jQuery.timeago() on shout's span.timeago | ||
if (jQuery.timeago) { | ||
// Reset timeago to use the new timestamp | ||
lastChainTimestamp.data('timeago', null).timeago(); | ||
} | ||
// else span.timeago text will be empty, but timeString will appear on hover <-- see templates/shoutbox/shout.tpl | ||
Shoutbox.utils.scrollToBottom(shoutContent); | ||
Shoutbox.vars.lastSid = shout.sid; | ||
} | ||
}, | ||
getShouts: function(shoutBox) { | ||
socket.emit(sb.config.sockets.get, function(err, shouts) { | ||
getShouts: function(shoutPanel) { | ||
Shoutbox.sockets.getShouts(function(err, shouts) { | ||
if (shouts.length === 0) { | ||
sb.utils.showEmptyMessage(shoutBox); | ||
Shoutbox.utils.showMessage(Shoutbox.vars.messages.empty, shoutPanel); | ||
} else { | ||
for(var i = 0; i < shouts.length; i++) { | ||
Base.addShout(shoutBox, shouts[i]); | ||
Shoutbox.base.addShout(shouts[i], shoutPanel); | ||
} | ||
//Base.updateUserStatus(shoutBox); | ||
} | ||
}); | ||
}, | ||
scrollToBottom: function(shoutContent) { | ||
if(shoutContent[0]) { | ||
shoutContent.scrollTop( | ||
shoutContent[0].scrollHeight - shoutContent.height() | ||
); | ||
} | ||
}, | ||
updateUserStatus: function(shoutBox, uid, status) { | ||
updateUserStatus: function(uid, status, shoutPanel) { | ||
var getStatus = function(uid) { | ||
socket.emit(sb.config.sockets.getUserStatus, uid, function(err, data) { | ||
Shoutbox.sockets.getUserStatus(uid, function(err, data) { | ||
setStatus(uid, data.status); | ||
}); | ||
} | ||
}; | ||
var setStatus = function(uid, status) { | ||
shoutBox.find('[data-uid="' + uid + '"] .shoutbox-shout-avatar').removeClass().addClass('shoutbox-shout-avatar ' + status); | ||
} | ||
shoutPanel.find('[data-uid="' + uid + '"] .shoutbox-shout-avatar-link').removeClass().addClass('shoutbox-shout-avatar-link ' + status); | ||
}; | ||
if (!uid) { | ||
uid = []; | ||
shoutBox.find('[data-uid]').each(function(index, el){ | ||
shoutPanel.find('[data-uid]').each(function(index, el){ | ||
uid.push($(el).data('uid')) | ||
@@ -70,3 +97,3 @@ }); | ||
} else if (Array.isArray(uid)) { | ||
for(var i = 0, l = uid.length; i < l; i++) { | ||
for (var i = 0, l = uid.length; i < l; i++) { | ||
getStatus(uid[i]); | ||
@@ -79,3 +106,3 @@ } | ||
} else if (Array.isArray(uid)) { | ||
for(var i = 0, l = uid.length; i < l; i++) { | ||
for (var i = 0, l = uid.length; i < l; i++) { | ||
setStatus(uid[i], status); | ||
@@ -87,19 +114,25 @@ } | ||
updateUsers: function() { | ||
socket.emit(sb.config.sockets.getUsers, { set: 'users:online', after: 0 }, function(err, data) { | ||
var userCount = data.users.length; | ||
var usernames = data.users.map(function(i) { | ||
return (i.username === null ? 'Anonymous' : i.username); | ||
}); | ||
var userString = usernames.join('; '); | ||
Base.getUsersPanel().find('.panel-body').text(userString); | ||
Base.getUsersPanel().find('.panel-title').text('Users (' + userCount + ')'); | ||
Shoutbox.sockets.getUsers({ set: 'users:online', after: 0 }, function(err, data) { | ||
var userCount = data.users.length, | ||
usernames = data.users.map(function(i) { | ||
return (i.username === null ? 'Anonymous' : i.username); | ||
}), | ||
userString = usernames.join('; '); | ||
Shoutbox.base.getUsersPanel().find('.panel-body').text(userString); | ||
Shoutbox.base.getUsersPanel().find('.panel-title').text('Users (' + userCount + ')'); | ||
}); | ||
if(Base.userCheck === 0) { | ||
Base.userCheck = setInterval(function() { | ||
Base.updateUsers(); | ||
if(Shoutbox.base.userCheck === 0) { | ||
Shoutbox.base.userCheck = setInterval(function() { | ||
Shoutbox.base.updateUsers(); | ||
}, 10000); | ||
} | ||
}, | ||
showUserPanel: function() { | ||
Base.getUsersPanel().parent().removeClass('hidden'); | ||
Base.updateUsers(); | ||
}, | ||
getShoutPanel: function() { | ||
return $('#shoutbox'); | ||
return Base.vars.shoutPanel || $('#shoutbox'); | ||
}, | ||
@@ -110,2 +143,3 @@ getUsersPanel: function() { | ||
vars: { | ||
shoutPanel: null, | ||
userCheck: 0 | ||
@@ -115,6 +149,8 @@ } | ||
return function(Shoutbox) { | ||
Shoutbox.base = Base; | ||
sb = Shoutbox; | ||
Shoutbox.base = { | ||
initialize: Base.initialize, | ||
addShout: Base.addShout, | ||
getShoutPanel: Base.getShoutPanel, | ||
updateUserStatus: Base.updateUserStatus | ||
}; | ||
}); | ||
})(window.Shoutbox); |
@@ -1,70 +0,105 @@ | ||
define(function() { | ||
var sb; | ||
var Sockets = { | ||
onreceive: { | ||
register: function() { | ||
if (socket.listeners(sb.config.sockets.onReceive).length === 0) { | ||
socket.on(sb.config.sockets.onReceive, this.handle); | ||
(function(Shoutbox) { | ||
var Messages = { | ||
getShouts: 'plugins.shoutbox.get', | ||
sendShout: 'plugins.shoutbox.send', | ||
removeShout : 'plugins.shoutbox.remove', | ||
editShout: 'plugins.shoutbox.edit', | ||
notifyStartTyping: 'plugins.shoutbox.notifyStartTyping', | ||
notifyStopTyping: 'plugins.shoutbox.notifyStopTyping', | ||
getOriginalShout: 'plugins.shoutbox.getOriginalShout', | ||
saveSettings: 'plugins.shoutbox.saveSetting', | ||
getSettings: 'plugins.shoutbox.getSettings', | ||
getUsers: 'user.loadMore', | ||
getUserStatus: 'user.isOnline' | ||
}; | ||
var Events = { | ||
onUserStatusChange: Messages.getUserStatus, | ||
onReceive: 'event:shoutbox.receive', | ||
onDelete: 'event:shoutbox.delete', | ||
onEdit: 'event:shoutbox.edit', | ||
onStartTyping: 'event:shoutbox.startTyping', | ||
onStopTyping: 'event:shoutbox.stopTyping' | ||
}; | ||
var Handlers = { | ||
onReceive: function(data) { | ||
var shoutPanel = Shoutbox.base.getShoutPanel(); | ||
if (shoutPanel.length > 0) { | ||
Shoutbox.base.addShout(data, shoutPanel); | ||
if (data.fromuid !== app.uid) { | ||
Shoutbox.utils.notify(data); | ||
} | ||
}, | ||
handle: function(data) { | ||
var shoutBox = sb.base.getShoutPanel(); | ||
if (shoutBox.length > 0) { | ||
sb.base.addShout(shoutBox, data); | ||
if (data.fromuid !== app.uid) { | ||
if (sb.config.getSetting('notification') === 1) { | ||
app.alternatingTitle(sb.config.messages.alert.replace(/%u/g, data.user.username)); | ||
} | ||
if (sb.config.getSetting('sound') === 1) { | ||
$('#shoutbox-sounds-notification')[0].play(); | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
ondelete: { | ||
register: function() { | ||
if (socket.listeners(sb.config.sockets.onDelete).length === 0) { | ||
socket.on(sb.config.sockets.onDelete, this.handle); | ||
} | ||
}, | ||
handle: function(data) { | ||
var par = $('[data-sid="' + data.sid + '"]').parents('[data-uid]'); | ||
if (par.find('[data-sid]').length === 1) { | ||
par.remove(); | ||
} else { | ||
$('[data-sid="' + data.sid + '"]').remove(); | ||
} | ||
if (data.sid === sb.actions.edit.editing) { | ||
sb.actions.edit.finish(sb.base.getShoutPanel()); | ||
} | ||
onDelete: function(data) { | ||
var selector = $('[data-sid="' + data.sid + '"]'), | ||
par = selector.parents('[data-uid]'); | ||
if (par.find('[data-sid]').length === 1) { | ||
par.remove(); | ||
} else { | ||
selector.remove(); | ||
} | ||
if (data.sid === Shoutbox.vars.editing) { | ||
Shoutbox.actions.finishEdit(Shoutbox.base.getShoutPanel()); | ||
} | ||
}, | ||
onedit: { | ||
register: function() { | ||
if (socket.listeners(sb.config.sockets.onEdit).length === 0) { | ||
socket.on(sb.config.sockets.onEdit, this.handle); | ||
onEdit: function(data) { | ||
data.content = '<abbr title="edited">' + data.content + '</abbr>'; | ||
$('[data-sid="' + data.sid + '"]').replaceWith(Shoutbox.utils.parseShout(data, true)); | ||
}, | ||
onUserStatusChange: function(err, data) { | ||
Shoutbox.base.updateUserStatus(data.uid, data.status, Shoutbox.base.getShoutPanel()); | ||
}, | ||
onStartTyping: function(data) { | ||
$('[data-uid="' + data.uid + '"]').addClass('isTyping'); | ||
}, | ||
onStopTyping: function(data) { | ||
$('[data-uid="' + data.uid + '"]').removeClass('isTyping'); | ||
}, | ||
defaultSocketHandler: function(message) { | ||
this.message = message; | ||
var self = this; | ||
return function (data, callback) { | ||
if (typeof data === 'function') { | ||
callback = data; | ||
data = null; | ||
} | ||
}, | ||
handle: function(data) { | ||
data.content = $(data.content).wrapInner('<abbr title="edited"></abbr>').html(); | ||
$('[data-sid="' + data.sid + '"]').html(sb.utils.parseShout(data, true)); | ||
socket.emit(self.message, data, callback); | ||
}; | ||
} | ||
}; | ||
Shoutbox.sockets = { | ||
messages: Messages, | ||
events: Events, | ||
registerMessage: function(handle, message) { | ||
if (!Shoutbox.sockets.hasOwnProperty(handle)) { | ||
Shoutbox.sockets[handle] = new Handlers.defaultSocketHandler(message); | ||
} | ||
}, | ||
onstatuschange: { | ||
register: function() { | ||
if (socket.listeners(sb.config.sockets.getUserStatus).length === 0) { | ||
socket.on(sb.config.sockets.getUserStatus, this.handle); | ||
registerEvent: function(event, handler) { | ||
if (socket.listeners(event).length === 0) { | ||
socket.on(event, handler); | ||
} | ||
}, | ||
initialize: function() { | ||
for (var e in Events) { | ||
if (Events.hasOwnProperty(e)) { | ||
this.registerEvent(Events[e], Handlers[e]); | ||
} | ||
}, | ||
handle: function(err, data) { | ||
sb.base.updateUserStatus(sb.base.getShoutPanel(), data.uid, data.status); | ||
} | ||
for (var m in Messages) { | ||
if (Messages.hasOwnProperty(m)) { | ||
this.registerMessage(m, Messages[m]); | ||
} | ||
} | ||
} | ||
}; | ||
return function(Shoutbox) { | ||
Shoutbox.sockets = Sockets; | ||
sb = Shoutbox; | ||
}; | ||
}); | ||
})(window.Shoutbox); |
@@ -1,6 +0,14 @@ | ||
define(function() { | ||
var sb, shoutTpl, textTpl; | ||
(function(Shoutbox) { | ||
var shoutTpl, textTpl, | ||
sounds; | ||
require(['sounds'], function(s) { | ||
sounds = s; | ||
}); | ||
var Utils = { | ||
init: function(callback) { | ||
initialize: function(shoutPanel, callback) { | ||
Shoutbox.sockets.initialize(); | ||
Shoutbox.actions.initialize(shoutPanel); | ||
if (!shoutTpl || !textTpl) { | ||
@@ -11,7 +19,7 @@ window.ajaxify.loadTemplate('shoutbox/shout', function(shout) { | ||
textTpl = text; | ||
callback(); | ||
Shoutbox.settings.load(shoutPanel, callback); | ||
}); | ||
}); | ||
} else { | ||
callback(); | ||
Shoutbox.settings.load(shoutPanel, callback); | ||
} | ||
@@ -24,85 +32,55 @@ }, | ||
}, | ||
prepareShoutbox: function() { | ||
Utils.getSettings(function() { | ||
var shoutBox = sb.base.getShoutPanel(); | ||
//if (shoutBox.length > 0 && Config.settings.hide !== 1) { | ||
// shoutBox.parents('.shoutbox-row').removeClass('hide'); | ||
if (shoutBox.length > 0) { | ||
Utils.parseSettings(shoutBox); | ||
Utils.registerHandlers(shoutBox); | ||
sb.base.getShouts(shoutBox); | ||
scrollToBottom: function(shoutContent) { | ||
if (shoutContent[0]) { | ||
var lastShoutHeight = $('[data-sid]:last').height(), | ||
scrollHeight = Utils.getScrollHeight(shoutContent) - lastShoutHeight; | ||
if (scrollHeight < Shoutbox.vars.scrollBreakpoint) { | ||
shoutContent.scrollTop( | ||
shoutContent[0].scrollHeight - shoutContent.height() | ||
); | ||
} | ||
}); | ||
} | ||
}, | ||
getSettings: function(callback) { | ||
socket.emit(sb.config.sockets.getSettings, function(err, settings) { | ||
sb.config.settings = settings.settings; | ||
sb.config.vars.shoutLimit = settings.shoutLimit; | ||
if(callback) { | ||
callback(); | ||
} | ||
}); | ||
}, | ||
parseSettings: function(shoutBox) { | ||
var settings = sb.config.settings; | ||
if (!settings) { | ||
return; | ||
getScrollHeight: function(shoutContent) { | ||
if (shoutContent[0]) { | ||
var padding = shoutContent.css('padding-top').replace('px', '') + shoutContent.css('padding-bottom').replace('px', ''); | ||
return (((shoutContent[0].scrollHeight - shoutContent.scrollTop()) - shoutContent.height()) - padding); | ||
} else { | ||
return -1; | ||
} | ||
for(var key in settings) { | ||
if (settings.hasOwnProperty(key)) { | ||
var value = settings[key]; | ||
var el = shoutBox.find('#shoutbox-settings-' + key + ' span'); | ||
// Not the best way but it'll have to do for now | ||
if (key !== 'hide') { | ||
if (value === 1) { | ||
el.removeClass('fa-times').addClass('fa-check'); | ||
} else { | ||
el.removeClass('fa-check').addClass('fa-times'); | ||
} | ||
} else { | ||
if (value == 1) { | ||
el.removeClass('fa-arrow-up').addClass('fa-arrow-down'); | ||
} else { | ||
el.removeClass('fa-arrow-down').addClass('fa-arrow-up'); | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
registerHandlers: function(shoutBox) { | ||
Utils.addActionHandlers(shoutBox); | ||
Utils.addSocketHandlers(); | ||
isAnon: function() { | ||
return app.uid === 0; | ||
}, | ||
addActionHandlers: function(shoutBox) { | ||
var actions = sb.actions; | ||
for (var a in actions) { | ||
if (actions.hasOwnProperty(a)) { | ||
actions[a].register(shoutBox); | ||
} | ||
} | ||
showMessage: function(message) { | ||
$('#shoutbox-content-overlay').find('span').html(message).parent().addClass('active'); | ||
}, | ||
addSocketHandlers: function() { | ||
var sockets = sb.sockets; | ||
for (var s in sockets) { | ||
if (sockets.hasOwnProperty(s)) { | ||
sockets[s].register(); | ||
} | ||
} | ||
closeMessage: function() { | ||
$('#shoutbox-content-overlay').removeClass('active'); | ||
}, | ||
checkAnon: function(callback) { | ||
if (app.uid === 0) { | ||
return callback(true); | ||
notify: function(data) { | ||
if (parseInt(Shoutbox.settings.get('toggles.notification'), 10) === 1) { | ||
app.alternatingTitle(Shoutbox.vars.messages.alert.replace(/%u/g, data.user.username)); | ||
} | ||
return callback(false); | ||
if (parseInt(Shoutbox.settings.get('toggles.sound'), 10) === 1) { | ||
Shoutbox.utils.playSound('notification'); | ||
} | ||
}, | ||
showEmptyMessage: function(shoutBox) { | ||
shoutBox.find('#shoutbox-content').html(Config.messages.empty); | ||
playSound: function(sound) { | ||
sounds.playFile('shoutbox-' + sound + '.mp3'); | ||
} | ||
}; | ||
return function(Shoutbox) { | ||
Shoutbox.utils = Utils; | ||
sb = Shoutbox; | ||
Shoutbox.utils = { | ||
initialize: Utils.initialize, | ||
parseShout: Utils.parseShout, | ||
scrollToBottom: Utils.scrollToBottom, | ||
getScrollHeight: Utils.getScrollHeight, | ||
showMessage: Utils.showMessage, | ||
isAnon: Utils.isAnon, | ||
notify: Utils.notify, | ||
playSound: Utils.playSound | ||
}; | ||
}); | ||
})(window.Shoutbox); | ||
@@ -1,11 +0,13 @@ | ||
$(document).ready(function() { | ||
$(window).on('action:ajaxify.end', function(e, data) { | ||
if (data.url === "" || data.url === "shoutbox") { | ||
require([ | ||
'plugins/nodebb-plugin-shoutbox/public/js/lib/shoutbox.js' | ||
], function(shoutBox) { | ||
shoutBox.init(data.url); | ||
}); | ||
(function() { | ||
$(window).on('action:widgets.loaded', function(e, data) { | ||
if ($('#shoutbox').length > 0) { | ||
Shoutbox.init(data.url); | ||
} | ||
}); | ||
}); | ||
window.Shoutbox = { | ||
init: function(url) { | ||
Shoutbox.base.initialize(url, $('#shoutbox')); | ||
} | ||
}; | ||
})(); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
69293
37
1634
3