commit
2641efd7f7
@ -0,0 +1,13 @@ |
||||
RocketChat.saveRoomAnnouncement = function(rid, roomAnnouncement, user, sendMessage=true) { |
||||
if (!Match.test(rid, String)) { |
||||
throw new Meteor.Error('invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomAnnouncement' }); |
||||
} |
||||
|
||||
roomAnnouncement = s.escapeHTML(roomAnnouncement); |
||||
const updated = RocketChat.models.Rooms.setAnnouncementById(rid, roomAnnouncement); |
||||
if (updated && sendMessage) { |
||||
RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_announcement', rid, roomAnnouncement, user); |
||||
} |
||||
|
||||
return updated; |
||||
}; |
@ -1,256 +0,0 @@ |
||||
Grid = Npm.require('gridfs-stream') |
||||
stream = Npm.require('stream') |
||||
fs = Npm.require('fs') |
||||
path = Npm.require('path') |
||||
mkdirp = Npm.require('mkdirp') |
||||
gm = Npm.require('gm') |
||||
exec = Npm.require('child_process').exec |
||||
|
||||
# Fix problem with usernames being converted to object id |
||||
Grid.prototype.tryParseObjectId = -> false |
||||
|
||||
RocketChatFile = |
||||
gm: gm |
||||
enabled: undefined |
||||
enable: -> |
||||
RocketChatFile.enabled = true |
||||
RocketChat.settings.updateOptionsById 'Accounts_AvatarResize', {alert: undefined} |
||||
disable: -> |
||||
RocketChatFile.enabled = false |
||||
RocketChat.settings.updateOptionsById 'Accounts_AvatarResize', {alert: 'The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server'} |
||||
|
||||
|
||||
detectGM = -> |
||||
exec 'gm version', Meteor.bindEnvironment (error, stdout, stderr) -> |
||||
if not error? and stdout.indexOf('GraphicsMagick') > -1 |
||||
RocketChatFile.enable() |
||||
|
||||
RocketChat.Info.GraphicsMagick = |
||||
enabled: true |
||||
version: stdout |
||||
else |
||||
RocketChat.Info.GraphicsMagick = |
||||
enabled: false |
||||
|
||||
exec 'convert -version', Meteor.bindEnvironment (error, stdout, stderr) -> |
||||
if not error? and stdout.indexOf('ImageMagick') > -1 |
||||
if RocketChatFile.enabled isnt true |
||||
# Enable GM to work with ImageMagick if no GraphicsMagick |
||||
RocketChatFile.gm = RocketChatFile.gm.subClass({imageMagick: true}) |
||||
RocketChatFile.enable() |
||||
|
||||
RocketChat.Info.ImageMagick = |
||||
enabled: true |
||||
version: stdout |
||||
else |
||||
if RocketChatFile.enabled isnt true |
||||
RocketChatFile.disable() |
||||
|
||||
RocketChat.Info.ImageMagick = |
||||
enabled: false |
||||
|
||||
detectGM() |
||||
|
||||
Meteor.methods |
||||
'detectGM': -> |
||||
detectGM() |
||||
return |
||||
|
||||
|
||||
RocketChatFile.bufferToStream = (buffer) -> |
||||
bufferStream = new stream.PassThrough() |
||||
bufferStream.end buffer |
||||
return bufferStream |
||||
|
||||
RocketChatFile.dataURIParse = (dataURI) -> |
||||
imageData = dataURI.split ';base64,' |
||||
return { |
||||
image: imageData[1] |
||||
contentType: imageData[0].replace('data:', '') |
||||
} |
||||
|
||||
RocketChatFile.addPassThrough = (st, fn) -> |
||||
pass = new stream.PassThrough() |
||||
fn pass, st |
||||
return pass |
||||
|
||||
|
||||
RocketChatFile.GridFS = class |
||||
constructor: (config={}) -> |
||||
{name, transformWrite} = config |
||||
|
||||
name ?= 'file' |
||||
|
||||
this.name = name |
||||
this.transformWrite = transformWrite |
||||
|
||||
mongo = Package.mongo.MongoInternals.NpmModule |
||||
db = Package.mongo.MongoInternals.defaultRemoteCollectionDriver().mongo.db |
||||
|
||||
this.store = new Grid(db, mongo) |
||||
this.findOneSync = Meteor.wrapAsync this.store.collection(this.name).findOne.bind this.store.collection(this.name) |
||||
this.removeSync = Meteor.wrapAsync this.store.remove.bind this.store |
||||
|
||||
this.getFileSync = Meteor.wrapAsync this.getFile.bind this |
||||
|
||||
findOne: (fileName) -> |
||||
return this.findOneSync {_id: fileName} |
||||
|
||||
remove: (fileName) -> |
||||
return this.removeSync |
||||
_id: fileName |
||||
root: this.name |
||||
|
||||
createWriteStream: (fileName, contentType) -> |
||||
self = this |
||||
|
||||
ws = this.store.createWriteStream |
||||
_id: fileName |
||||
filename: fileName |
||||
mode: 'w' |
||||
root: this.name |
||||
content_type: contentType |
||||
|
||||
if self.transformWrite? |
||||
ws = RocketChatFile.addPassThrough ws, (rs, ws) -> |
||||
file = |
||||
name: self.name |
||||
fileName: fileName |
||||
contentType: contentType |
||||
|
||||
self.transformWrite file, rs, ws |
||||
|
||||
ws.on 'close', -> |
||||
ws.emit 'end' |
||||
|
||||
return ws |
||||
|
||||
createReadStream: (fileName) -> |
||||
return this.store.createReadStream |
||||
_id: fileName |
||||
root: this.name |
||||
return undefined |
||||
|
||||
getFileWithReadStream: (fileName) -> |
||||
file = this.findOne fileName |
||||
if not file? |
||||
return undefined |
||||
|
||||
rs = this.createReadStream fileName |
||||
|
||||
return { |
||||
readStream: rs |
||||
contentType: file.contentType |
||||
length: file.length |
||||
uploadDate: file.uploadDate |
||||
} |
||||
|
||||
getFile: (fileName, cb) -> |
||||
file = this.getFileWithReadStream(fileName) |
||||
|
||||
if not file |
||||
return cb() |
||||
|
||||
data = [] |
||||
file.readStream.on 'data', Meteor.bindEnvironment (chunk) -> |
||||
data.push chunk |
||||
|
||||
file.readStream.on 'end', Meteor.bindEnvironment -> |
||||
cb null, |
||||
buffer: Buffer.concat(data) |
||||
contentType: file.contentType |
||||
length: file.length |
||||
uploadDate: file.uploadDate |
||||
|
||||
deleteFile: (fileName) -> |
||||
file = this.findOne fileName |
||||
if not file? |
||||
return undefined |
||||
|
||||
return this.remove fileName |
||||
|
||||
|
||||
RocketChatFile.FileSystem = class |
||||
constructor: (config={}) -> |
||||
{absolutePath, transformWrite} = config |
||||
|
||||
absolutePath ?= '~/uploads' |
||||
|
||||
this.transformWrite = transformWrite |
||||
|
||||
if absolutePath.split(path.sep)[0] is '~' |
||||
homepath = process.env.HOME or process.env.HOMEPATH or process.env.USERPROFILE |
||||
if homepath? |
||||
absolutePath = absolutePath.replace '~', homepath |
||||
else |
||||
throw new Error('Unable to resolve "~" in path') |
||||
|
||||
this.absolutePath = path.resolve absolutePath |
||||
mkdirp.sync this.absolutePath |
||||
this.statSync = Meteor.wrapAsync fs.stat.bind fs |
||||
this.unlinkSync = Meteor.wrapAsync fs.unlink.bind fs |
||||
|
||||
this.getFileSync = Meteor.wrapAsync this.getFile.bind this |
||||
|
||||
createWriteStream: (fileName, contentType) -> |
||||
self = this |
||||
|
||||
ws = fs.createWriteStream path.join this.absolutePath, fileName |
||||
|
||||
if self.transformWrite? |
||||
ws = RocketChatFile.addPassThrough ws, (rs, ws) -> |
||||
file = |
||||
fileName: fileName |
||||
contentType: contentType |
||||
|
||||
self.transformWrite file, rs, ws |
||||
|
||||
ws.on 'close', -> |
||||
ws.emit 'end' |
||||
|
||||
return ws |
||||
|
||||
createReadStream: (fileName) -> |
||||
return fs.createReadStream path.join this.absolutePath, fileName |
||||
|
||||
stat: (fileName) -> |
||||
return this.statSync path.join this.absolutePath, fileName |
||||
|
||||
remove: (fileName) -> |
||||
return this.unlinkSync path.join this.absolutePath, fileName |
||||
|
||||
getFileWithReadStream: (fileName) -> |
||||
try |
||||
stat = this.stat fileName |
||||
rs = this.createReadStream fileName |
||||
|
||||
return { |
||||
readStream: rs |
||||
# contentType: file.contentType |
||||
length: stat.size |
||||
} |
||||
catch e |
||||
return undefined |
||||
|
||||
getFile: (fileName, cb) -> |
||||
file = this.getFileWithReadStream(fileName) |
||||
|
||||
if not file |
||||
return cb() |
||||
|
||||
data = [] |
||||
file.readStream.on 'data', Meteor.bindEnvironment (chunk) -> |
||||
data.push chunk |
||||
|
||||
file.readStream.on 'end', Meteor.bindEnvironment -> |
||||
buffer: Buffer.concat(data) |
||||
contentType: file.contentType |
||||
length: file.length |
||||
uploadDate: file.uploadDate |
||||
|
||||
deleteFile: (fileName) -> |
||||
try |
||||
stat = this.stat fileName |
||||
return this.remove fileName |
||||
catch e |
||||
return undefined |
@ -0,0 +1,292 @@ |
||||
import Grid from 'gridfs-stream'; |
||||
import stream from 'stream'; |
||||
import fs from 'fs'; |
||||
import path from 'path'; |
||||
import mkdirp from 'mkdirp'; |
||||
import gm from 'gm'; |
||||
import {exec} from 'child_process'; |
||||
|
||||
// Fix problem with usernames being converted to object id
|
||||
Grid.prototype.tryParseObjectId = function() { |
||||
return false; |
||||
}; |
||||
//TODO: REMOVE RocketChatFile from globals
|
||||
RocketChatFile = { |
||||
gm, |
||||
enabled: undefined, |
||||
enable() { |
||||
RocketChatFile.enabled = true; |
||||
return RocketChat.settings.updateOptionsById('Accounts_AvatarResize', { |
||||
alert: undefined |
||||
}); |
||||
}, |
||||
disable() { |
||||
RocketChatFile.enabled = false; |
||||
return RocketChat.settings.updateOptionsById('Accounts_AvatarResize', { |
||||
alert: 'The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server' |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
const detectGM = function() { |
||||
return exec('gm version', Meteor.bindEnvironment(function(error, stdout) { |
||||
if ((error == null) && stdout.indexOf('GraphicsMagick') > -1) { |
||||
RocketChatFile.enable(); |
||||
RocketChat.Info.GraphicsMagick = { |
||||
enabled: true, |
||||
version: stdout |
||||
}; |
||||
} else { |
||||
RocketChat.Info.GraphicsMagick = { |
||||
enabled: false |
||||
}; |
||||
} |
||||
return exec('convert -version', Meteor.bindEnvironment(function(error, stdout) { |
||||
if ((error == null) && stdout.indexOf('ImageMagick') > -1) { |
||||
if (RocketChatFile.enabled !== true) { |
||||
// Enable GM to work with ImageMagick if no GraphicsMagick
|
||||
RocketChatFile.gm = RocketChatFile.gm.subClass({ |
||||
imageMagick: true |
||||
}); |
||||
RocketChatFile.enable(); |
||||
} |
||||
return RocketChat.Info.ImageMagick = { |
||||
enabled: true, |
||||
version: stdout |
||||
}; |
||||
} else { |
||||
if (RocketChatFile.enabled !== true) { |
||||
RocketChatFile.disable(); |
||||
} |
||||
return RocketChat.Info.ImageMagick = { |
||||
enabled: false |
||||
}; |
||||
} |
||||
})); |
||||
})); |
||||
}; |
||||
|
||||
detectGM(); |
||||
|
||||
Meteor.methods({ |
||||
'detectGM'() { |
||||
detectGM(); |
||||
} |
||||
}); |
||||
|
||||
RocketChatFile.bufferToStream = function(buffer) { |
||||
const bufferStream = new stream.PassThrough(); |
||||
bufferStream.end(buffer); |
||||
return bufferStream; |
||||
}; |
||||
|
||||
RocketChatFile.dataURIParse = function(dataURI) { |
||||
const imageData = dataURI.split(';base64,'); |
||||
return { |
||||
image: imageData[1], |
||||
contentType: imageData[0].replace('data:', '') |
||||
}; |
||||
}; |
||||
|
||||
RocketChatFile.addPassThrough = function(st, fn) { |
||||
const pass = new stream.PassThrough(); |
||||
fn(pass, st); |
||||
return pass; |
||||
}; |
||||
|
||||
RocketChatFile.GridFS = class { |
||||
constructor(config = {}) { |
||||
const {name = 'file', transformWrite} = config; |
||||
|
||||
this.name = name; |
||||
this.transformWrite = transformWrite; |
||||
const mongo = Package.mongo.MongoInternals.NpmModule; |
||||
const db = Package.mongo.MongoInternals.defaultRemoteCollectionDriver().mongo.db; |
||||
this.store = new Grid(db, mongo); |
||||
this.findOneSync = Meteor.wrapAsync(this.store.collection(this.name).findOne.bind(this.store.collection(this.name))); |
||||
this.removeSync = Meteor.wrapAsync(this.store.remove.bind(this.store)); |
||||
this.getFileSync = Meteor.wrapAsync(this.getFile.bind(this)); |
||||
} |
||||
|
||||
findOne(fileName) { |
||||
return this.findOneSync({ |
||||
_id: fileName |
||||
}); |
||||
} |
||||
|
||||
remove(fileName) { |
||||
return this.removeSync({ |
||||
_id: fileName, |
||||
root: this.name |
||||
}); |
||||
} |
||||
|
||||
createWriteStream(fileName, contentType) { |
||||
const self = this; |
||||
let ws = this.store.createWriteStream({ |
||||
_id: fileName, |
||||
filename: fileName, |
||||
mode: 'w', |
||||
root: this.name, |
||||
content_type: contentType |
||||
}); |
||||
if (self.transformWrite != null) { |
||||
ws = RocketChatFile.addPassThrough(ws, function(rs, ws) { |
||||
const file = { |
||||
name: self.name, |
||||
fileName, |
||||
contentType |
||||
}; |
||||
return self.transformWrite(file, rs, ws); |
||||
}); |
||||
} |
||||
ws.on('close', function() { |
||||
return ws.emit('end'); |
||||
}); |
||||
return ws; |
||||
} |
||||
|
||||
createReadStream(fileName) { |
||||
return this.store.createReadStream({ |
||||
_id: fileName, |
||||
root: this.name |
||||
}); |
||||
} |
||||
|
||||
getFileWithReadStream(fileName) { |
||||
const file = this.findOne(fileName); |
||||
if (file == null) { |
||||
return null; |
||||
} |
||||
const rs = this.createReadStream(fileName); |
||||
return { |
||||
readStream: rs, |
||||
contentType: file.contentType, |
||||
length: file.length, |
||||
uploadDate: file.uploadDate |
||||
}; |
||||
} |
||||
|
||||
getFile(fileName, cb) { |
||||
const file = this.getFileWithReadStream(fileName); |
||||
if (!file) { |
||||
return cb(); |
||||
} |
||||
const data = []; |
||||
file.readStream.on('data', Meteor.bindEnvironment(function(chunk) { |
||||
return data.push(chunk); |
||||
})); |
||||
return file.readStream.on('end', Meteor.bindEnvironment(function() { |
||||
return cb(null, { |
||||
buffer: Buffer.concat(data), |
||||
contentType: file.contentType, |
||||
length: file.length, |
||||
uploadDate: file.uploadDate |
||||
}); |
||||
})); |
||||
} |
||||
|
||||
deleteFile(fileName) { |
||||
const file = this.findOne(fileName); |
||||
if (file == null) { |
||||
return undefined; |
||||
} |
||||
return this.remove(fileName); |
||||
} |
||||
|
||||
|
||||
}; |
||||
|
||||
RocketChatFile.FileSystem = class { |
||||
constructor(config = {}) { |
||||
let {absolutePath = '~/uploads'} = config; |
||||
const {transformWrite} = config; |
||||
|
||||
this.transformWrite = transformWrite; |
||||
if (absolutePath.split(path.sep)[0] === '~') { |
||||
const homepath = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; |
||||
if (homepath != null) { |
||||
absolutePath = absolutePath.replace('~', homepath); |
||||
} else { |
||||
throw new Error('Unable to resolve "~" in path'); |
||||
} |
||||
} |
||||
this.absolutePath = path.resolve(absolutePath); |
||||
mkdirp.sync(this.absolutePath); |
||||
this.statSync = Meteor.wrapAsync(fs.stat.bind(fs)); |
||||
this.unlinkSync = Meteor.wrapAsync(fs.unlink.bind(fs)); |
||||
this.getFileSync = Meteor.wrapAsync(this.getFile.bind(this)); |
||||
} |
||||
|
||||
createWriteStream(fileName, contentType) { |
||||
const self = this; |
||||
let ws = fs.createWriteStream(path.join(this.absolutePath, fileName)); |
||||
if (self.transformWrite != null) { |
||||
ws = RocketChatFile.addPassThrough(ws, function(rs, ws) { |
||||
const file = { |
||||
fileName, |
||||
contentType |
||||
}; |
||||
return self.transformWrite(file, rs, ws); |
||||
}); |
||||
} |
||||
ws.on('close', function() { |
||||
return ws.emit('end'); |
||||
}); |
||||
return ws; |
||||
} |
||||
|
||||
createReadStream(fileName) { |
||||
return fs.createReadStream(path.join(this.absolutePath, fileName)); |
||||
} |
||||
|
||||
stat(fileName) { |
||||
return this.statSync(path.join(this.absolutePath, fileName)); |
||||
} |
||||
|
||||
remove(fileName) { |
||||
return this.unlinkSync(path.join(this.absolutePath, fileName)); |
||||
} |
||||
|
||||
getFileWithReadStream(fileName) { |
||||
try { |
||||
const stat = this.stat(fileName); |
||||
const rs = this.createReadStream(fileName); |
||||
return { |
||||
readStream: rs, |
||||
// contentType: file.contentType
|
||||
length: stat.size |
||||
}; |
||||
} catch (error1) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
getFile(fileName, cb) { |
||||
const file = this.getFileWithReadStream(fileName); |
||||
if (!file) { |
||||
return cb(); |
||||
} |
||||
const data = []; |
||||
file.readStream.on('data', Meteor.bindEnvironment(function(chunk) { |
||||
return data.push(chunk); |
||||
})); |
||||
return file.readStream.on('end', Meteor.bindEnvironment(function() { |
||||
return { |
||||
buffer: Buffer.concat(data)({ |
||||
contentType: file.contentType, |
||||
length: file.length, |
||||
uploadDate: file.uploadDate |
||||
}) |
||||
}; |
||||
})); |
||||
} |
||||
|
||||
deleteFile(fileName) { |
||||
try { |
||||
return this.remove(fileName); |
||||
} catch (error1) { |
||||
return null; |
||||
} |
||||
} |
||||
}; |
@ -1,26 +0,0 @@ |
||||
### |
||||
# MapView is a named function that will replace geolocation in messages with a Google Static Map |
||||
# @param {Object} message - The message object |
||||
### |
||||
|
||||
class MapView |
||||
constructor: (message) -> |
||||
|
||||
# get MapView settings |
||||
mv_googlekey = RocketChat.settings.get 'MapView_GMapsAPIKey' |
||||
|
||||
if message.location |
||||
|
||||
# GeoJSON is reversed - ie. [lng, lat] |
||||
longitude = message.location.coordinates[0] |
||||
latitude = message.location.coordinates[1] |
||||
|
||||
# confirm we have an api key set, and generate the html required for the mapview |
||||
if mv_googlekey?.length |
||||
message.html = '<a href="https://maps.google.com/maps?daddr='+latitude+','+longitude+'" target="_blank"><img src="https://maps.googleapis.com/maps/api/staticmap?zoom=14&size=250x250&markers=color:gray%7Clabel:%7C'+latitude+','+longitude+'&key='+mv_googlekey+'" /></a>' |
||||
else |
||||
message.html = '<a href="https://maps.google.com/maps?daddr='+latitude+','+longitude+'" target="_blank">'+TAPi18n.__('Shared_Location')+'</a>' |
||||
|
||||
return message |
||||
|
||||
RocketChat.callbacks.add 'renderMessage', MapView, RocketChat.callbacks.priority.HIGH |
@ -0,0 +1,27 @@ |
||||
/* |
||||
* MapView is a named function that will replace geolocation in messages with a Google Static Map |
||||
* @param {Object} message - The message object |
||||
*/ |
||||
|
||||
function MapView(message) { |
||||
|
||||
// get MapView settings
|
||||
const mv_googlekey = RocketChat.settings.get('MapView_GMapsAPIKey'); |
||||
|
||||
if (message.location) { |
||||
|
||||
// GeoJSON is reversed - ie. [lng, lat]
|
||||
const [longitude, latitude] = message.location.coordinates; |
||||
|
||||
// confirm we have an api key set, and generate the html required for the mapview
|
||||
if (mv_googlekey && mv_googlekey.length) { |
||||
message.html = `<a href="https://maps.google.com/maps?daddr=${ latitude },${ longitude }" target="_blank"><img src="https://maps.googleapis.com/maps/api/staticmap?zoom=14&size=250x250&markers=color:gray%7Clabel:%7C${ latitude },${ longitude }&key=${ mv_googlekey }" /></a>`; |
||||
} else { |
||||
message.html = `<a href="https://maps.google.com/maps?daddr=${ latitude },${ longitude }" target="_blank">${ TAPi18n.__('Shared_Location') }</a>`; |
||||
} |
||||
} |
||||
|
||||
return message; |
||||
} |
||||
|
||||
RocketChat.callbacks.add('renderMessage', MapView, RocketChat.callbacks.priority.HIGH); |
@ -1,3 +0,0 @@ |
||||
Meteor.startup -> |
||||
RocketChat.settings.add 'MapView_Enabled', false, {type: 'boolean', group: 'Message', section: 'Google Maps', public: true, i18nLabel: 'MapView_Enabled', i18nDescription: 'MapView_Enabled_Description'} |
||||
RocketChat.settings.add 'MapView_GMapsAPIKey', '', {type: 'string', group: 'Message', section: 'Google Maps', public: true, i18nLabel: 'MapView_GMapsAPIKey', i18nDescription: 'MapView_GMapsAPIKey_Description'} |
@ -0,0 +1,4 @@ |
||||
Meteor.startup(function() { |
||||
RocketChat.settings.add('MapView_Enabled', false, {type: 'boolean', group: 'Message', section: 'Google Maps', public: true, i18nLabel: 'MapView_Enabled', i18nDescription: 'MapView_Enabled_Description'}); |
||||
return RocketChat.settings.add('MapView_GMapsAPIKey', '', {type: 'string', group: 'Message', section: 'Google Maps', public: true, i18nLabel: 'MapView_GMapsAPIKey', i18nDescription: 'MapView_GMapsAPIKey_Description'}); |
||||
}); |
@ -1,55 +0,0 @@ |
||||
### |
||||
# Mentions is a named function that will process Mentions |
||||
# @param {Object} message - The message object |
||||
### |
||||
|
||||
class MentionsClient |
||||
constructor: (message) -> |
||||
if _.trim message.html |
||||
msg = message.html |
||||
|
||||
mentions = [] |
||||
|
||||
msgMentionRegex = new RegExp '(?:^|\\s|\\n)(?:@)(' + RocketChat.settings.get('UTF8_Names_Validation') + ')', 'g' |
||||
message.msg.replace msgMentionRegex, (match, mention) -> |
||||
mentions.push mention |
||||
|
||||
me = Meteor.user()?.username |
||||
|
||||
if mentions.length isnt 0 |
||||
mentions = _.unique mentions |
||||
mentions = mentions.join('|') |
||||
msg = msg.replace new RegExp("(?:^|\\s|\\n)(@(#{mentions}):?)[:.,\s]?", 'g'), (match, mention, username) -> |
||||
if username is 'all' or username is 'here' |
||||
return match.replace mention, "<a class=\"mention-link mention-link-me mention-link-all background-attention-color\">#{mention}</a>" |
||||
|
||||
if not message.temp? |
||||
if not _.findWhere(message.mentions, {username: username})? |
||||
return match |
||||
|
||||
classes = 'mention-link' |
||||
if username is me |
||||
classes += ' mention-link-me background-primary-action-color' |
||||
|
||||
return match.replace mention, "<a class=\"#{classes}\" data-username=\"#{username}\">#{mention}</a>" |
||||
|
||||
channels = [] |
||||
msgChannelRegex = new RegExp '(?:^|\\s|\\n)(?:#)(' + RocketChat.settings.get('UTF8_Names_Validation') + ')', 'g' |
||||
message.msg.replace msgChannelRegex, (match, mention) -> |
||||
channels.push mention |
||||
|
||||
if channels.length isnt 0 |
||||
channels = _.unique channels |
||||
channels = channels.join('|') |
||||
msg = msg.replace new RegExp("(?:^|\\s|\\n)(#(#{channels}))[:.,\s]?", 'g'), (match, mention, channel) -> |
||||
if not message.temp? |
||||
if not _.findWhere(message.channels, {name: channel})? |
||||
return match |
||||
return match.replace mention, "<a class=\"mention-link\" data-channel=\"#{channel}\">#{mention}</a>" |
||||
|
||||
|
||||
message.html = msg |
||||
return message |
||||
|
||||
RocketChat.callbacks.add 'renderMessage', MentionsClient, RocketChat.callbacks.priority.MEDIUM, 'mentions-message' |
||||
RocketChat.callbacks.add 'renderMentions', MentionsClient, RocketChat.callbacks.priority.MEDIUM, 'mentions-mentions' |
@ -0,0 +1,41 @@ |
||||
/* |
||||
* Mentions is a named function that will process Mentions |
||||
* @param {Object} message - The message object |
||||
*/ |
||||
|
||||
function MentionsClient(message) { |
||||
let msg = (message && message.html) || ''; |
||||
if (!msg.trim()) { |
||||
return message; |
||||
} |
||||
const msgMentionRegex = new RegExp(`(?:^|\\s|\\n)(@(${ RocketChat.settings.get('UTF8_Names_Validation') }):?)[:.,\s]?`, 'g'); |
||||
|
||||
let me = Meteor.user(); |
||||
me = me ? me.username : null; |
||||
|
||||
msg = msg.replace(msgMentionRegex, function(match, mention, username) { |
||||
if (['all', 'here'].includes(username)) { |
||||
return match.replace(mention, `<a class="mention-link mention-link-me mention-link-all background-attention-color">${ mention }</a>`); |
||||
} |
||||
if (message.temp == null && _.findWhere(message.mentions, {username}) == null) { |
||||
return match; |
||||
} |
||||
return match.replace(mention, `<a class="mention-link ${ username === me ? 'mention-link-me background-primary-action-color':'' }" data-username="${ username }">${ mention }</a>`); |
||||
}); |
||||
|
||||
const msgChannelRegex = new RegExp(`(?:^|\\s|\\n)(#(${ RocketChat.settings.get('UTF8_Names_Validation') }))[:.,\s]?`, 'g'); |
||||
|
||||
msg = msg.replace(msgChannelRegex, function(match, mention, name) { |
||||
if (message.temp == null && _.findWhere(message.channels, {name}) == null) { |
||||
return match; |
||||
} |
||||
return match.replace(mention, `<a class="mention-link" data-channel="${ name }">${ mention }</a>`); |
||||
}); |
||||
message.html = msg; |
||||
return message; |
||||
} |
||||
|
||||
|
||||
RocketChat.callbacks.add('renderMessage', MentionsClient, RocketChat.callbacks.priority.MEDIUM, 'mentions-message'); |
||||
|
||||
RocketChat.callbacks.add('renderMentions', MentionsClient, RocketChat.callbacks.priority.MEDIUM, 'mentions-mentions'); |
@ -1,56 +0,0 @@ |
||||
### |
||||
# Mentions is a named function that will process Mentions |
||||
# @param {Object} message - The message object |
||||
### |
||||
|
||||
class MentionsServer |
||||
constructor: (message) -> |
||||
# If message starts with /me, replace it for text formatting |
||||
mentions = [] |
||||
msgMentionRegex = new RegExp '(?:^|\\s|\\n)(?:@)(' + RocketChat.settings.get('UTF8_Names_Validation') + ')', 'g' |
||||
message.msg.replace msgMentionRegex, (match, mention) -> |
||||
mentions.push mention |
||||
if mentions.length isnt 0 |
||||
mentions = _.unique mentions |
||||
verifiedMentions = [] |
||||
mentions.forEach (mention) -> |
||||
if mention is 'all' |
||||
messageMaxAll = RocketChat.settings.get('Message_MaxAll') |
||||
if messageMaxAll > 0 |
||||
allChannel = RocketChat.models.Rooms.findOneById message.rid |
||||
if allChannel.usernames.length <= messageMaxAll |
||||
verifiedMention = |
||||
_id: mention |
||||
username: mention |
||||
else |
||||
verifiedMention = |
||||
_id: mention |
||||
username: mention |
||||
else if mention is 'here' |
||||
verifiedMention = |
||||
_id: mention |
||||
username: mention |
||||
else |
||||
verifiedMention = Meteor.users.findOne({username: mention}, {fields: {_id: 1, username: 1}}) |
||||
|
||||
verifiedMentions.push verifiedMention if verifiedMention? |
||||
if verifiedMentions.length isnt 0 |
||||
message.mentions = verifiedMentions |
||||
|
||||
channels = [] |
||||
msgChannelRegex = new RegExp '(?:^|\\s|\\n)(?:#)(' + RocketChat.settings.get('UTF8_Names_Validation') + ')', 'g' |
||||
message.msg.replace msgChannelRegex, (match, mention) -> |
||||
channels.push mention |
||||
|
||||
if channels.length isnt 0 |
||||
channels = _.unique channels |
||||
verifiedChannels = [] |
||||
channels.forEach (mention) -> |
||||
verifiedChannel = RocketChat.models.Rooms.findOneByNameAndType(mention, 'c', { fields: {_id: 1, name: 1 } }) |
||||
verifiedChannels.push verifiedChannel if verifiedChannel? |
||||
|
||||
if verifiedChannels.length isnt 0 |
||||
message.channels = verifiedChannels |
||||
return message |
||||
|
||||
RocketChat.callbacks.add 'beforeSaveMessage', MentionsServer, RocketChat.callbacks.priority.HIGH, 'mentions' |
@ -0,0 +1,49 @@ |
||||
/* |
||||
* Mentions is a named function that will process Mentions |
||||
* @param {Object} message - The message object |
||||
*/ |
||||
|
||||
function MentionsServer(message) { |
||||
const msgMentionRegex = new RegExp(`(?:^|\\s|\\n)(?:@)(${ RocketChat.settings.get('UTF8_Names_Validation') })`, 'g'); |
||||
const mentionsAll = []; |
||||
const userMentions = []; |
||||
let mentions = message.msg.match(msgMentionRegex); |
||||
if (mentions) { |
||||
mentions.forEach((m) => { |
||||
const mention = m.trim().substr(1); |
||||
if (mention !== 'all' && mention !== 'here') { |
||||
return userMentions.push(mention); |
||||
} |
||||
if (mention === 'all') { |
||||
const messageMaxAll = RocketChat.settings.get('Message_MaxAll'); |
||||
const allChannel = RocketChat.models.Rooms.findOneById(message.rid); |
||||
if (messageMaxAll !== 0 && allChannel.usernames.length >= messageMaxAll) { |
||||
return; |
||||
} |
||||
} |
||||
mentionsAll.push({ |
||||
_id: mention, |
||||
username: mention |
||||
}); |
||||
}); |
||||
mentions = userMentions.length ? Meteor.users.find({ username: {$in: _.unique(userMentions)}}, { fields: {_id: true, username: true }}).fetch() : []; |
||||
|
||||
const verifiedMentions = [...mentionsAll, ...mentions]; |
||||
if (verifiedMentions.length !== 0) { |
||||
message.mentions = verifiedMentions; |
||||
} |
||||
} |
||||
|
||||
const msgChannelRegex = new RegExp(`(?:^|\\s|\\n)(?:#)(${ RocketChat.settings.get('UTF8_Names_Validation') })`, 'g'); |
||||
let channels = message.msg.match(msgChannelRegex); |
||||
if (channels) { |
||||
channels = channels.map(c => c.trim().substr(1)); |
||||
const verifiedChannels = RocketChat.models.Rooms.find({ name: {$in: _.unique(channels)}, t: 'c' }, { fields: {_id: 1, name: 1 }}).fetch(); |
||||
if (verifiedChannels.length !== 0) { |
||||
message.channels = verifiedChannels; |
||||
} |
||||
} |
||||
return message; |
||||
} |
||||
|
||||
RocketChat.callbacks.add('beforeSaveMessage', MentionsServer, RocketChat.callbacks.priority.HIGH, 'mentions'); |
@ -1,63 +0,0 @@ |
||||
import moment from 'moment' |
||||
|
||||
fixCordova = (url) -> |
||||
if url?.indexOf('data:image') is 0 |
||||
return url |
||||
|
||||
if Meteor.isCordova and url?[0] is '/' |
||||
url = Meteor.absoluteUrl().replace(/\/$/, '') + url |
||||
query = "rc_uid=#{Meteor.userId()}&rc_token=#{Meteor._localStorage.getItem('Meteor.loginToken')}" |
||||
if url.indexOf('?') is -1 |
||||
url = url + '?' + query |
||||
else |
||||
url = url + '&' + query |
||||
|
||||
if Meteor.settings.public.sandstorm or url.match /^(https?:)?\/\//i |
||||
return url |
||||
else if navigator.userAgent.indexOf('Electron') > -1 |
||||
return __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url |
||||
else |
||||
return Meteor.absoluteUrl().replace(/\/$/, '') + __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url |
||||
|
||||
Template.messageAttachment.helpers |
||||
fixCordova: fixCordova |
||||
|
||||
parsedText: -> |
||||
renderMessageBody { msg: this.text } |
||||
|
||||
loadImage: -> |
||||
if Meteor.user()?.settings?.preferences?.autoImageLoad is false and this.downloadImages? is not true |
||||
return false |
||||
|
||||
if Meteor.Device.isPhone() and Meteor.user()?.settings?.preferences?.saveMobileBandwidth and this.downloadImages? is not true |
||||
return false |
||||
|
||||
return true |
||||
|
||||
getImageHeight: (height) -> |
||||
return height or 200 |
||||
|
||||
color: -> |
||||
switch @color |
||||
when 'good' then return '#35AC19' |
||||
when 'warning' then return '#FCB316' |
||||
when 'danger' then return '#D30230' |
||||
else return @color |
||||
|
||||
collapsed: -> |
||||
if this.collapsed? |
||||
return this.collapsed |
||||
else |
||||
return Meteor.user()?.settings?.preferences?.collapseMediaByDefault is true |
||||
|
||||
time: -> |
||||
messageDate = new Date(@ts) |
||||
today = new Date() |
||||
if messageDate.toDateString() is today.toDateString() |
||||
return moment(@ts).format(RocketChat.settings.get('Message_TimeFormat')) |
||||
else |
||||
return moment(@ts).format(RocketChat.settings.get('Message_TimeAndDateFormat')) |
||||
|
||||
injectIndex: (data, previousIndex, index) -> |
||||
data.index = previousIndex + '.attachments.' + index |
||||
return |
@ -0,0 +1,74 @@ |
||||
import moment from 'moment'; |
||||
const colors = { |
||||
good: '#35AC19', |
||||
warning: '#FCB316', |
||||
danger: '#D30230' |
||||
}; |
||||
const fixCordova = function(url) { |
||||
if (url && url.indexOf('data:image') === 0) { |
||||
return url; |
||||
} |
||||
if (Meteor.isCordova && (url && url[0] === '/')) { |
||||
url = Meteor.absoluteUrl().replace(/\/$/, '') + url; |
||||
const query = `rc_uid=${ Meteor.userId() }&rc_token=${ Meteor._localStorage.getItem('Meteor.loginToken') }`; |
||||
if (url.indexOf('?') === -1) { |
||||
url = `${ url }?${ query }`; |
||||
} else { |
||||
url = `${ url }&${ query }`; |
||||
} |
||||
} |
||||
if (Meteor.settings['public'].sandstorm || url.match(/^(https?:)?\/\//i)) { |
||||
return url; |
||||
} else if (navigator.userAgent.indexOf('Electron') > -1) { |
||||
return __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url; |
||||
} else { |
||||
return Meteor.absoluteUrl().replace(/\/$/, '') + __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url; |
||||
} |
||||
}; |
||||
/*globals renderMessageBody*/ |
||||
Template.messageAttachment.helpers({ |
||||
fixCordova, |
||||
parsedText() { |
||||
return renderMessageBody({ |
||||
msg: this.text |
||||
}); |
||||
}, |
||||
loadImage() { |
||||
const user = Meteor.user(); |
||||
if (user && user.settings && user.settings.preferences && this.downloadImages !== true) { |
||||
if (user.settings.preferences.autoImageLoad === false) { |
||||
return false; |
||||
} |
||||
if (Meteor.Device.isPhone() && user.settings.preferences.saveMobileBandwidth !== true) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
}, |
||||
getImageHeight(height = 200) { |
||||
return height; |
||||
}, |
||||
color() { |
||||
return colors[this.color] || this.color; |
||||
}, |
||||
collapsed() { |
||||
if (this.collapsed != null) { |
||||
return this.collapsed; |
||||
} else { |
||||
const user = Meteor.user(); |
||||
return user && user.settings && user.settings.preferences && user.settings.preferences.collapseMediaByDefault === true; |
||||
} |
||||
}, |
||||
time() { |
||||
const messageDate = new Date(this.ts); |
||||
const today = new Date(); |
||||
if (messageDate.toDateString() === today.toDateString()) { |
||||
return moment(this.ts).format(RocketChat.settings.get('Message_TimeFormat')); |
||||
} else { |
||||
return moment(this.ts).format(RocketChat.settings.get('Message_TimeAndDateFormat')); |
||||
} |
||||
}, |
||||
injectIndex(data, previousIndex, index) { |
||||
data.index = `${ previousIndex }.attachments.${ index }`; |
||||
} |
||||
}); |
@ -1,3 +0,0 @@ |
||||
RocketChat.slashCommands.add 'invite', undefined, |
||||
description: 'Invite_user_to_join_channel' |
||||
params: '@username' |
@ -0,0 +1,4 @@ |
||||
RocketChat.slashCommands.add('invite', undefined, { |
||||
description: 'Invite_user_to_join_channel', |
||||
params: '@username' |
||||
}); |
@ -1,68 +0,0 @@ |
||||
### |
||||
# Invite is a named function that will replace /invite commands |
||||
# @param {Object} message - The message object |
||||
### |
||||
|
||||
class Invite |
||||
constructor: (command, params, item) -> |
||||
if command isnt 'invite' or not Match.test params, String |
||||
return |
||||
|
||||
usernames = params.replace(/@/g, '').split(/[\s,]/).filter((a) -> '' != a) |
||||
if 0 == usernames.length |
||||
return |
||||
|
||||
users = Meteor.users.find({ username: { $in: usernames }}) |
||||
currentUser = Meteor.users.findOne Meteor.userId() |
||||
|
||||
if 0 == users.count() |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__('User_doesnt_exist', { postProcess: 'sprintf', sprintf: [ usernames.join(' @') ] }, currentUser.language) |
||||
} |
||||
return |
||||
|
||||
usernames = usernames.filter((username) -> |
||||
if not RocketChat.models.Rooms.findOneByIdContainingUsername(item.rid, username)? |
||||
return true |
||||
|
||||
# Cancel if user is already in this room |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__('Username_is_already_in_here', { postProcess: 'sprintf', sprintf: [ username ] }, currentUser.language) |
||||
} |
||||
return false |
||||
) |
||||
|
||||
# Cancel if all users is already in this room |
||||
if 0 == usernames.length |
||||
return |
||||
|
||||
users.forEach((user) -> |
||||
try |
||||
Meteor.call 'addUserToRoom', |
||||
rid: item.rid |
||||
username: user.username |
||||
catch e |
||||
if e.error is 'cant-invite-for-direct-room' |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__('Cannot_invite_users_to_direct_rooms', null, currentUser.language) |
||||
} |
||||
else |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__(e.error, null, currentUser.language) |
||||
} |
||||
return |
||||
) |
||||
|
||||
RocketChat.slashCommands.add 'invite', Invite |
@ -0,0 +1,82 @@ |
||||
|
||||
/* |
||||
* Invite is a named function that will replace /invite commands |
||||
* @param {Object} message - The message object |
||||
*/ |
||||
|
||||
|
||||
function Invite(command, params, item) { |
||||
|
||||
if (command !== 'invite' || !Match.test(params, String)) { |
||||
return; |
||||
} |
||||
let usernames = params.replace(/@/g, '').split(/[\s,]/).filter((a) => a !== ''); |
||||
if (usernames.length === 0) { |
||||
return; |
||||
} |
||||
const users = Meteor.users.find({ |
||||
username: { |
||||
$in: usernames |
||||
} |
||||
}); |
||||
const currentUser = Meteor.users.findOne(Meteor.userId()); |
||||
if (users.count() === 0) { |
||||
RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__('User_doesnt_exist', { |
||||
postProcess: 'sprintf', |
||||
sprintf: [usernames.join(' @')] |
||||
}, currentUser.language) |
||||
}); |
||||
return; |
||||
} |
||||
usernames = usernames.filter(function(username) { |
||||
if (RocketChat.models.Rooms.findOneByIdContainingUsername(item.rid, username) == null) { |
||||
return true; |
||||
} |
||||
RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__('Username_is_already_in_here', { |
||||
postProcess: 'sprintf', |
||||
sprintf: [username] |
||||
}, currentUser.language) |
||||
}); |
||||
return false; |
||||
}); |
||||
if (usernames.length === 0) { |
||||
return; |
||||
} |
||||
users.forEach(function(user) { |
||||
|
||||
try { |
||||
return Meteor.call('addUserToRoom', { |
||||
rid: item.rid, |
||||
username: user.username |
||||
}); |
||||
} catch ({error}) { |
||||
if (error === 'cant-invite-for-direct-room') { |
||||
RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__('Cannot_invite_users_to_direct_rooms', null, currentUser.language) |
||||
}); |
||||
} else { |
||||
RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__(error, null, currentUser.language) |
||||
}); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
RocketChat.slashCommands.add('invite', Invite); |
||||
|
||||
export {Invite}; |
@ -1,8 +0,0 @@ |
||||
RocketChat.slashCommands.add 'join', undefined, |
||||
description: 'Join_the_given_channel' |
||||
params: '#channel' |
||||
(err, result, params) -> |
||||
if err.error == 'error-user-already-in-room' |
||||
params.cmd = 'open' |
||||
params.msg.msg = params.msg.msg.replace('join', 'open') |
||||
RocketChat.slashCommands.run 'open', params.params, params.msg |
@ -0,0 +1,10 @@ |
||||
RocketChat.slashCommands.add('join', undefined, { |
||||
description: 'Join_the_given_channel', |
||||
params: '#channel' |
||||
}, function(err, result, params) { |
||||
if (err.error === 'error-user-already-in-room') { |
||||
params.cmd = 'open'; |
||||
params.msg.msg = params.msg.msg.replace('join', 'open'); |
||||
return RocketChat.slashCommands.run('open', params.params, params.msg); |
||||
} |
||||
}); |
@ -1,33 +0,0 @@ |
||||
### |
||||
# Join is a named function that will replace /join commands |
||||
# @param {Object} message - The message object |
||||
### |
||||
|
||||
class Join |
||||
constructor: (command, params, item) -> |
||||
if command isnt 'join' or not Match.test params, String |
||||
return |
||||
|
||||
channel = params.trim() |
||||
if channel is '' |
||||
return |
||||
|
||||
channel = channel.replace('#', '') |
||||
|
||||
user = Meteor.users.findOne Meteor.userId() |
||||
room = RocketChat.models.Rooms.findOneByNameAndType channel, 'c' |
||||
|
||||
if not room |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__('Channel_doesnt_exist', { postProcess: 'sprintf', sprintf: [ channel ] }, user.language) |
||||
|
||||
throw new Meteor.Error('error-user-already-in-room', 'You are already in the channel', { |
||||
method: 'slashCommands' |
||||
}) if room.usernames.indexOf(user.username) > -1 |
||||
|
||||
Meteor.call 'joinRoom', room._id |
||||
|
||||
RocketChat.slashCommands.add 'join', Join |
@ -0,0 +1,37 @@ |
||||
|
||||
/* |
||||
* Join is a named function that will replace /join commands |
||||
* @param {Object} message - The message object |
||||
*/ |
||||
|
||||
|
||||
RocketChat.slashCommands.add('join', function Join(command, params, item) { |
||||
|
||||
if (command !== 'join' || !Match.test(params, String)) { |
||||
return; |
||||
} |
||||
let channel = params.trim(); |
||||
if (channel === '') { |
||||
return; |
||||
} |
||||
channel = channel.replace('#', ''); |
||||
const user = Meteor.users.findOne(Meteor.userId()); |
||||
const room = RocketChat.models.Rooms.findOneByNameAndType(channel, 'c'); |
||||
if (!room) { |
||||
RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__('Channel_doesnt_exist', { |
||||
postProcess: 'sprintf', |
||||
sprintf: [channel] |
||||
}, user.language) |
||||
}); |
||||
} |
||||
if (room.usernames.includes(user.username)) { |
||||
throw new Meteor.Error('error-user-already-in-room', 'You are already in the channel', { |
||||
method: 'slashCommands' |
||||
}); |
||||
} |
||||
Meteor.call('joinRoom', room._id); |
||||
}); |
@ -1,28 +0,0 @@ |
||||
### |
||||
# Leave is a named function that will replace /leave commands |
||||
# @param {Object} message - The message object |
||||
### |
||||
|
||||
if Meteor.isClient |
||||
RocketChat.slashCommands.add 'leave', undefined, |
||||
description: 'Leave_the_current_channel' |
||||
|
||||
RocketChat.slashCommands.add 'part', undefined, |
||||
description: 'Leave_the_current_channel' |
||||
|
||||
else |
||||
class Leave |
||||
constructor: (command, params, item) -> |
||||
if(command == "leave" || command == "part") |
||||
try |
||||
Meteor.call 'leaveRoom', item.rid |
||||
catch err |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__(err.error, null, Meteor.user().language) |
||||
} |
||||
|
||||
RocketChat.slashCommands.add 'leave', Leave |
||||
RocketChat.slashCommands.add 'part', Leave |
@ -0,0 +1,31 @@ |
||||
|
||||
/* |
||||
* Leave is a named function that will replace /leave commands |
||||
* @param {Object} message - The message object |
||||
*/ |
||||
function Leave(command, params, item) { |
||||
if (command !== 'leave' && command !== 'part') { |
||||
return; |
||||
} |
||||
try { |
||||
Meteor.call('leaveRoom', item.rid); |
||||
} catch ({error}) { |
||||
RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__(error, null, Meteor.user().language) |
||||
}); |
||||
} |
||||
} |
||||
if (Meteor.isClient) { |
||||
RocketChat.slashCommands.add('leave', undefined, { |
||||
description: 'Leave_the_current_channel' |
||||
}); |
||||
RocketChat.slashCommands.add('part', undefined, { |
||||
description: 'Leave_the_current_channel' |
||||
}); |
||||
} else { |
||||
RocketChat.slashCommands.add('leave', Leave); |
||||
RocketChat.slashCommands.add('part', Leave); |
||||
} |
@ -1,16 +0,0 @@ |
||||
### |
||||
# Me is a named function that will replace /me commands |
||||
# @param {Object} message - The message object |
||||
### |
||||
|
||||
class Me |
||||
constructor: (command, params, item) -> |
||||
if(command == "me") |
||||
if _.trim params |
||||
msg = item |
||||
msg.msg = '_' + params + '_' |
||||
Meteor.call 'sendMessage', msg |
||||
|
||||
RocketChat.slashCommands.add 'me', Me, |
||||
description: 'Displays_action_text' |
||||
params: 'your_message' |
@ -0,0 +1,18 @@ |
||||
|
||||
/* |
||||
* Me is a named function that will replace /me commands |
||||
* @param {Object} message - The message object |
||||
*/ |
||||
RocketChat.slashCommands.add('me', function Me(command, params, item) { |
||||
if (command !== 'me') { |
||||
return; |
||||
} |
||||
if (_.trim(params)) { |
||||
const msg = item; |
||||
msg.msg = `_${ params }_`; |
||||
Meteor.call('sendMessage', msg); |
||||
} |
||||
}, { |
||||
description: 'Displays_action_text', |
||||
params: 'your_message' |
||||
}); |
@ -1,3 +0,0 @@ |
||||
RocketChat.slashCommands.add 'msg', null, |
||||
description: 'Direct_message_someone' |
||||
params: '@username <message>' |
@ -0,0 +1,4 @@ |
||||
RocketChat.slashCommands.add('msg', undefined, { |
||||
description: 'Direct_message_someone', |
||||
params: '@username <message>' |
||||
}); |
@ -1,43 +0,0 @@ |
||||
### |
||||
# Msg is a named function that will replace /msg commands |
||||
### |
||||
|
||||
class Msg |
||||
constructor: (command, params, item) -> |
||||
if command isnt 'msg' or not Match.test params, String |
||||
return |
||||
|
||||
trimmedParams = params.trim() |
||||
separator = trimmedParams.indexOf(' ') |
||||
|
||||
user = Meteor.users.findOne Meteor.userId() |
||||
|
||||
if separator is -1 |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__('Username_and_message_must_not_be_empty', null, user.language) |
||||
} |
||||
return |
||||
|
||||
message = trimmedParams.slice(separator + 1) |
||||
|
||||
targetUsernameOrig = trimmedParams.slice(0, separator) |
||||
targetUsername = targetUsernameOrig.replace('@', '') |
||||
targetUser = RocketChat.models.Users.findOneByUsername targetUsername |
||||
|
||||
if not targetUser? |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__('Username_doesnt_exist', { postProcess: 'sprintf', sprintf: [ targetUsernameOrig ] }, user.language) |
||||
} |
||||
return |
||||
|
||||
rid = Meteor.call 'createDirectMessage', targetUsername |
||||
msgObject = { _id: Random.id(), rid: rid.rid, msg: message} |
||||
Meteor.call 'sendMessage', msgObject |
||||
|
||||
RocketChat.slashCommands.add 'msg', Msg |
@ -0,0 +1,46 @@ |
||||
|
||||
/* |
||||
* Msg is a named function that will replace /msg commands |
||||
*/ |
||||
|
||||
function Msg(command, params, item) { |
||||
if (command !== 'msg' || !Match.test(params, String)) { |
||||
return; |
||||
} |
||||
const trimmedParams = params.trim(); |
||||
const separator = trimmedParams.indexOf(' '); |
||||
const user = Meteor.users.findOne(Meteor.userId()); |
||||
if (separator === -1) { |
||||
return RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__('Username_and_message_must_not_be_empty', null, user.language) |
||||
}); |
||||
} |
||||
const message = trimmedParams.slice(separator + 1); |
||||
const targetUsernameOrig = trimmedParams.slice(0, separator); |
||||
const targetUsername = targetUsernameOrig.replace('@', ''); |
||||
const targetUser = RocketChat.models.Users.findOneByUsername(targetUsername); |
||||
if (targetUser == null) { |
||||
RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__('Username_doesnt_exist', { |
||||
postProcess: 'sprintf', |
||||
sprintf: [targetUsernameOrig] |
||||
}, user.language) |
||||
}); |
||||
return; |
||||
} |
||||
const {rid} = Meteor.call('createDirectMessage', targetUsername); |
||||
const msgObject = { |
||||
_id: Random.id(), |
||||
rid, |
||||
msg: message |
||||
}; |
||||
Meteor.call('sendMessage', msgObject); |
||||
} |
||||
|
||||
RocketChat.slashCommands.add('msg', Msg); |
@ -1,3 +0,0 @@ |
||||
RocketChat.slashCommands.add 'mute', null, |
||||
description: 'Mute_someone_in_room' |
||||
params: '@username' |
@ -0,0 +1,4 @@ |
||||
RocketChat.slashCommands.add('mute', undefined, { |
||||
description: 'Mute_someone_in_room', |
||||
params: '@username' |
||||
}); |
@ -1,3 +0,0 @@ |
||||
RocketChat.slashCommands.add 'unmute', null, |
||||
description: 'Unmute_someone_in_room' |
||||
params: '@username' |
@ -0,0 +1,4 @@ |
||||
RocketChat.slashCommands.add('unmute', undefined, { |
||||
description: 'Unmute_someone_in_room', |
||||
params: '@username' |
||||
}); |
@ -1,40 +0,0 @@ |
||||
### |
||||
# Mute is a named function that will replace /mute commands |
||||
### |
||||
|
||||
class Mute |
||||
constructor: (command, params, item) -> |
||||
if command isnt 'mute' or not Match.test params, String |
||||
return |
||||
|
||||
username = params.trim() |
||||
if username is '' |
||||
return |
||||
|
||||
username = username.replace('@', '') |
||||
|
||||
user = Meteor.users.findOne Meteor.userId() |
||||
mutedUser = RocketChat.models.Users.findOneByUsername username |
||||
room = RocketChat.models.Rooms.findOneById item.rid |
||||
|
||||
if not mutedUser? |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__('Username_doesnt_exist', { postProcess: 'sprintf', sprintf: [ username ] }, user.language); |
||||
} |
||||
return |
||||
|
||||
if username not in (room.usernames or []) |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__('Username_is_not_in_this_room', { postProcess: 'sprintf', sprintf: [ username ] }, user.language); |
||||
} |
||||
return |
||||
|
||||
Meteor.call 'muteUserInRoom', { rid: item.rid, username: username } |
||||
|
||||
RocketChat.slashCommands.add 'mute', Mute |
@ -0,0 +1,45 @@ |
||||
|
||||
/* |
||||
* Mute is a named function that will replace /mute commands |
||||
*/ |
||||
|
||||
RocketChat.slashCommands.add('mute', function Mute(command, params, item) { |
||||
if (command !== 'mute' || !Match.test(params, String)) { |
||||
return; |
||||
} |
||||
const username = params.trim().replace('@', ''); |
||||
if (username === '') { |
||||
return; |
||||
} |
||||
const user = Meteor.users.findOne(Meteor.userId()); |
||||
const mutedUser = RocketChat.models.Users.findOneByUsername(username); |
||||
const room = RocketChat.models.Rooms.findOneById(item.rid); |
||||
if (mutedUser == null) { |
||||
RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__('Username_doesnt_exist', { |
||||
postProcess: 'sprintf', |
||||
sprintf: [username] |
||||
}, user.language) |
||||
}); |
||||
return; |
||||
} |
||||
if ((room.usernames || []).includes(username)) { |
||||
RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__('Username_is_not_in_this_room', { |
||||
postProcess: 'sprintf', |
||||
sprintf: [username] |
||||
}, user.language) |
||||
}); |
||||
return; |
||||
} |
||||
Meteor.call('muteUserInRoom', { |
||||
rid: item.rid, |
||||
username |
||||
}); |
||||
}); |
@ -1,40 +0,0 @@ |
||||
### |
||||
# Unmute is a named function that will replace /unmute commands |
||||
### |
||||
|
||||
class Unmute |
||||
constructor: (command, params, item) -> |
||||
if command isnt 'unmute' or not Match.test params, String |
||||
return |
||||
|
||||
username = params.trim() |
||||
if username is '' |
||||
return |
||||
|
||||
username = username.replace('@', '') |
||||
|
||||
user = Meteor.users.findOne Meteor.userId() |
||||
unmutedUser = RocketChat.models.Users.findOneByUsername username |
||||
room = RocketChat.models.Rooms.findOneById item.rid |
||||
|
||||
if not unmutedUser? |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__('Username_doesnt_exist', { postProcess: 'sprintf', sprintf: [ username ] }, user.language); |
||||
} |
||||
return |
||||
|
||||
if username not in (room.usernames or []) |
||||
RocketChat.Notifications.notifyUser Meteor.userId(), 'message', { |
||||
_id: Random.id() |
||||
rid: item.rid |
||||
ts: new Date |
||||
msg: TAPi18n.__('Username_is_not_in_this_room', { postProcess: 'sprintf', sprintf: [ username ] }, user.language); |
||||
} |
||||
return |
||||
|
||||
Meteor.call 'unmuteUserInRoom', { rid: item.rid, username: username } |
||||
|
||||
RocketChat.slashCommands.add 'unmute', Unmute |
@ -0,0 +1,44 @@ |
||||
|
||||
/* |
||||
* Unmute is a named function that will replace /unmute commands |
||||
*/ |
||||
|
||||
RocketChat.slashCommands.add('unmute', function Unmute(command, params, item) { |
||||
|
||||
if (command !== 'unmute' || !Match.test(params, String)) { |
||||
return; |
||||
} |
||||
const username = params.trim().replace('@', ''); |
||||
if (username === '') { |
||||
return; |
||||
} |
||||
const user = Meteor.users.findOne(Meteor.userId()); |
||||
const unmutedUser = RocketChat.models.Users.findOneByUsername(username); |
||||
const room = RocketChat.models.Rooms.findOneById(item.rid); |
||||
if (unmutedUser == null) { |
||||
return RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__('Username_doesnt_exist', { |
||||
postProcess: 'sprintf', |
||||
sprintf: [username] |
||||
}, user.language) |
||||
}); |
||||
} |
||||
if ((room.usernames || []).includes(username)) { |
||||
return RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', { |
||||
_id: Random.id(), |
||||
rid: item.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__('Username_is_not_in_this_room', { |
||||
postProcess: 'sprintf', |
||||
sprintf: [username] |
||||
}, user.language) |
||||
}); |
||||
} |
||||
Meteor.call('unmuteUserInRoom', { |
||||
rid: item.rid, |
||||
username |
||||
}); |
||||
}); |
@ -1,253 +0,0 @@ |
||||
`import Clipboard from 'clipboard';` |
||||
|
||||
Template.body.onRendered -> |
||||
clipboard = new Clipboard('.clipboard') |
||||
|
||||
$(document.body).on 'keydown', (e) -> |
||||
if e.keyCode in [80, 75] and (e.ctrlKey is true or e.metaKey is true) and e.shiftKey is false |
||||
e.preventDefault() |
||||
e.stopPropagation() |
||||
toolbarSearch.focus(true) |
||||
|
||||
unread = Session.get('unread') |
||||
if e.keyCode is 27 and e.shiftKey is true and unread? and unread isnt '' |
||||
e.preventDefault() |
||||
e.stopPropagation() |
||||
swal |
||||
title: t('Clear_all_unreads_question') |
||||
type: 'warning' |
||||
confirmButtonText: t('Yes_clear_all') |
||||
showCancelButton: true |
||||
cancelButtonText: t('Cancel') |
||||
confirmButtonColor: '#DD6B55' |
||||
, -> |
||||
subscriptions = ChatSubscription.find({open: true}, { fields: { unread: 1, alert: 1, rid: 1, t: 1, name: 1, ls: 1 } }) |
||||
for subscription in subscriptions.fetch() |
||||
if subscription.alert or subscription.unread > 0 |
||||
Meteor.call 'readMessages', subscription.rid |
||||
|
||||
$(document.body).on 'keydown', (e) -> |
||||
target = e.target |
||||
if(e.ctrlKey is true or e.metaKey is true) |
||||
return |
||||
if !(e.keyCode > 45 and e.keyCode < 91 or e.keyCode == 8) |
||||
return |
||||
if /input|textarea|select/i.test(target.tagName) |
||||
return |
||||
if target.id is 'pswp' |
||||
return |
||||
|
||||
inputMessage = $('textarea.input-message') |
||||
if inputMessage.length is 0 |
||||
return |
||||
inputMessage.focus() |
||||
|
||||
$(document.body).on 'click', 'a', (e) -> |
||||
link = e.currentTarget |
||||
if link.origin is s.rtrim(Meteor.absoluteUrl(), '/') and /msg=([a-zA-Z0-9]+)/.test(link.search) |
||||
e.preventDefault() |
||||
e.stopPropagation() |
||||
|
||||
if RocketChat.Layout.isEmbedded() |
||||
return fireGlobalEvent('click-message-link', { link: link.pathname + link.search }) |
||||
|
||||
FlowRouter.go(link.pathname + link.search, null, FlowRouter.current().queryParams) |
||||
|
||||
Tracker.autorun (c) -> |
||||
w = window |
||||
d = document |
||||
s = 'script' |
||||
l = 'dataLayer' |
||||
i = RocketChat.settings.get 'GoogleTagManager_id' |
||||
if Match.test(i, String) and i.trim() isnt '' |
||||
c.stop() |
||||
do (w,d,s,l,i) -> |
||||
w[l] = w[l] || [] |
||||
w[l].push {'gtm.start': new Date().getTime(), event:'gtm.js'} |
||||
f = d.getElementsByTagName(s)[0] |
||||
j = d.createElement(s) |
||||
dl = if l isnt 'dataLayer' then '&l=' + l else '' |
||||
j.async = true |
||||
j.src = '//www.googletagmanager.com/gtm.js?id=' + i + dl |
||||
f.parentNode.insertBefore j, f |
||||
|
||||
if Meteor.isCordova |
||||
$(document.body).addClass 'is-cordova' |
||||
|
||||
|
||||
Template.main.helpers |
||||
|
||||
siteName: -> |
||||
return RocketChat.settings.get 'Site_Name' |
||||
|
||||
logged: -> |
||||
if Meteor.userId()? |
||||
$('html').addClass("noscroll").removeClass("scroll") |
||||
return true |
||||
else |
||||
$('html').addClass("scroll").removeClass("noscroll") |
||||
return false |
||||
|
||||
useIframe: -> |
||||
iframeEnabled = (typeof RocketChat.iframeLogin isnt "undefined") |
||||
return (iframeEnabled and RocketChat.iframeLogin.reactiveEnabled.get()) |
||||
|
||||
iframeUrl: -> |
||||
iframeEnabled = (typeof RocketChat.iframeLogin isnt "undefined") |
||||
return (iframeEnabled and RocketChat.iframeLogin.reactiveIframeUrl.get()) |
||||
|
||||
subsReady: -> |
||||
routerReady = FlowRouter.subsReady('userData', 'activeUsers') |
||||
subscriptionsReady = CachedChatSubscription.ready.get() |
||||
|
||||
ready = not Meteor.userId()? or (routerReady and subscriptionsReady) |
||||
RocketChat.CachedCollectionManager.syncEnabled = ready |
||||
return ready |
||||
|
||||
hasUsername: -> |
||||
return Meteor.userId()? and Meteor.user().username? |
||||
|
||||
requirePasswordChange: -> |
||||
return Meteor.user()?.requirePasswordChange is true |
||||
|
||||
CustomScriptLoggedOut: -> |
||||
script = RocketChat.settings.get('Custom_Script_Logged_Out') or '' |
||||
if script.trim() |
||||
eval(script) |
||||
return |
||||
|
||||
CustomScriptLoggedIn: -> |
||||
script = RocketChat.settings.get('Custom_Script_Logged_In') or '' |
||||
if script.trim() |
||||
eval(script) |
||||
return |
||||
|
||||
embeddedVersion: -> |
||||
return 'embedded-view' if RocketChat.Layout.isEmbedded() |
||||
|
||||
Template.main.events |
||||
|
||||
"click .burger": -> |
||||
console.log 'room click .burger' if window.rocketDebug |
||||
menu.toggle() |
||||
|
||||
'touchstart': (e, t) -> |
||||
if document.body.clientWidth > 780 |
||||
return |
||||
|
||||
t.touchstartX = undefined |
||||
t.touchstartY = undefined |
||||
t.movestarted = false |
||||
t.blockmove = false |
||||
t.isRtl = isRtl localStorage.getItem "userLanguage" |
||||
if $(e.currentTarget).closest('.main-content').length > 0 |
||||
t.touchstartX = e.originalEvent.touches[0].clientX |
||||
t.touchstartY = e.originalEvent.touches[0].clientY |
||||
t.mainContent = $('.main-content') |
||||
t.wrapper = $('.messages-box > .wrapper') |
||||
|
||||
'touchmove': (e, t) -> |
||||
if t.touchstartX? |
||||
touch = e.originalEvent.touches[0] |
||||
diffX = touch.clientX - t.touchstartX |
||||
diffY = touch.clientY - t.touchstartY |
||||
absX = Math.abs(diffX) |
||||
absY = Math.abs(diffY) |
||||
|
||||
if t.movestarted isnt true and t.blockmove isnt true and absY > 5 |
||||
t.blockmove = true |
||||
|
||||
if t.blockmove isnt true and (t.movestarted is true or absX > 5) |
||||
t.movestarted = true |
||||
|
||||
if t.isRtl |
||||
if menu.isOpen() |
||||
t.diff = -260 + diffX |
||||
else |
||||
t.diff = diffX |
||||
|
||||
if t.diff < -260 |
||||
t.diff = -260 |
||||
if t.diff > 0 |
||||
t.diff = 0 |
||||
else |
||||
if menu.isOpen() |
||||
t.diff = 260 + diffX |
||||
else |
||||
t.diff = diffX |
||||
|
||||
if t.diff > 260 |
||||
t.diff = 260 |
||||
if t.diff < 0 |
||||
t.diff = 0 |
||||
|
||||
t.mainContent.addClass('notransition') |
||||
t.mainContent.css('transform', 'translate(' + t.diff + 'px)') |
||||
t.wrapper.css('overflow', 'hidden') |
||||
|
||||
'touchend': (e, t) -> |
||||
if t.movestarted is true |
||||
t.mainContent.removeClass('notransition') |
||||
t.wrapper.css('overflow', '') |
||||
|
||||
if t.isRtl |
||||
if menu.isOpen() |
||||
if t.diff >= -200 |
||||
menu.close() |
||||
else |
||||
menu.open() |
||||
else |
||||
if t.diff <= -60 |
||||
menu.open() |
||||
else |
||||
menu.close() |
||||
else |
||||
if menu.isOpen() |
||||
if t.diff >= 200 |
||||
menu.open() |
||||
else |
||||
menu.close() |
||||
else |
||||
if t.diff >= 60 |
||||
menu.open() |
||||
else |
||||
menu.close() |
||||
|
||||
Template.main.onRendered -> |
||||
|
||||
# RTL Support - Need config option on the UI |
||||
if isRtl localStorage.getItem "userLanguage" |
||||
$('html').addClass "rtl" |
||||
else |
||||
$('html').removeClass "rtl" |
||||
|
||||
$('#initial-page-loading').remove() |
||||
|
||||
window.addEventListener 'focus', -> |
||||
Meteor.setTimeout -> |
||||
if not $(':focus').is('INPUT,TEXTAREA') |
||||
$('.input-message').focus() |
||||
, 100 |
||||
|
||||
Tracker.autorun -> |
||||
swal.setDefaults({cancelButtonText: t('Cancel')}) |
||||
|
||||
prefs = Meteor.user()?.settings?.preferences |
||||
if prefs?.hideUsernames |
||||
$(document.body).on('mouseleave', 'button.thumb', (e) -> |
||||
RocketChat.tooltip.hide(); |
||||
) |
||||
|
||||
$(document.body).on('mouseenter', 'button.thumb', (e) -> |
||||
avatarElem = $(e.currentTarget) |
||||
username = avatarElem.attr('data-username') |
||||
if username |
||||
e.stopPropagation() |
||||
RocketChat.tooltip.showElement($('<span>').text(username), avatarElem) |
||||
) |
||||
else |
||||
$(document.body).off('mouseenter', 'button.thumb') |
||||
$(document.body).off('mouseleave', 'button.thumb') |
||||
|
||||
Meteor.startup -> |
||||
fireGlobalEvent 'startup', true |
@ -0,0 +1,301 @@ |
||||
/* globals toolbarSearch, menu, isRtl, fireGlobalEvent, CachedChatSubscription */ |
||||
import Clipboard from 'clipboard'; |
||||
|
||||
Template.body.onRendered(function() { |
||||
new Clipboard('.clipboard'); |
||||
|
||||
$(document.body).on('keydown', function(e) { |
||||
if ((e.keyCode === 80 || e.keyCode === 75) && (e.ctrlKey === true || e.metaKey === true) && e.shiftKey === false) { |
||||
e.preventDefault(); |
||||
e.stopPropagation(); |
||||
toolbarSearch.focus(true); |
||||
} |
||||
const unread = Session.get('unread'); |
||||
if (e.keyCode === 27 && e.shiftKey === true && (unread != null) && unread !== '') { |
||||
e.preventDefault(); |
||||
e.stopPropagation(); |
||||
return swal({ |
||||
title: t('Clear_all_unreads_question'), |
||||
type: 'warning', |
||||
confirmButtonText: t('Yes_clear_all'), |
||||
showCancelButton: true, |
||||
cancelButtonText: t('Cancel'), |
||||
confirmButtonColor: '#DD6B55' |
||||
}, function() { |
||||
const subscriptions = ChatSubscription.find({ |
||||
open: true |
||||
}, { |
||||
fields: { |
||||
unread: 1, |
||||
alert: 1, |
||||
rid: 1, |
||||
t: 1, |
||||
name: 1, |
||||
ls: 1 |
||||
} |
||||
}); |
||||
|
||||
subscriptions.forEach((subscription) =>{ |
||||
if (subscription.alert || subscription.unread > 0) { |
||||
Meteor.call('readMessages', subscription.rid); |
||||
} |
||||
}); |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
$(document.body).on('keydown', function(e) { |
||||
const target = e.target; |
||||
if (e.ctrlKey === true || e.metaKey === true) { |
||||
return; |
||||
} |
||||
if (!(e.keyCode > 45 && e.keyCode < 91 || e.keyCode === 8)) { |
||||
return; |
||||
} |
||||
if (/input|textarea|select/i.test(target.tagName)) { |
||||
return; |
||||
} |
||||
if (target.id === 'pswp') { |
||||
return; |
||||
} |
||||
const inputMessage = $('textarea.input-message'); |
||||
if (inputMessage.length === 0) { |
||||
return; |
||||
} |
||||
return inputMessage.focus(); |
||||
}); |
||||
$(document.body).on('click', 'a', function(e) { |
||||
const link = e.currentTarget; |
||||
if (link.origin === s.rtrim(Meteor.absoluteUrl(), '/') && /msg=([a-zA-Z0-9]+)/.test(link.search)) { |
||||
e.preventDefault(); |
||||
e.stopPropagation(); |
||||
if (RocketChat.Layout.isEmbedded()) { |
||||
return fireGlobalEvent('click-message-link', { |
||||
link: link.pathname + link.search |
||||
}); |
||||
} |
||||
return FlowRouter.go(link.pathname + link.search, null, FlowRouter.current().queryParams); |
||||
} |
||||
}); |
||||
Tracker.autorun(function(c) { |
||||
const w = window; |
||||
const d = document; |
||||
const s = 'script'; |
||||
const l = 'dataLayer'; |
||||
const i = RocketChat.settings.get('GoogleTagManager_id'); |
||||
if (Match.test(i, String) && i.trim() !== '') { |
||||
c.stop(); |
||||
return (function(w, d, s, l, i) { |
||||
w[l] = w[l] || []; |
||||
w[l].push({ |
||||
'gtm.start': new Date().getTime(), |
||||
event: 'gtm.js' |
||||
}); |
||||
const f = d.getElementsByTagName(s)[0]; |
||||
const j = d.createElement(s); |
||||
const dl = l !== 'dataLayer' ? `&l=${ l }` : ''; |
||||
j.async = true; |
||||
j.src = `//www.googletagmanager.com/gtm.js?id=${ i }${ dl }`; |
||||
return f.parentNode.insertBefore(j, f); |
||||
}(w, d, s, l, i)); |
||||
} |
||||
}); |
||||
if (Meteor.isCordova) { |
||||
return $(document.body).addClass('is-cordova'); |
||||
} |
||||
}); |
||||
|
||||
Template.main.helpers({ |
||||
siteName() { |
||||
return RocketChat.settings.get('Site_Name'); |
||||
}, |
||||
logged() { |
||||
if (Meteor.userId() != null) { |
||||
$('html').addClass('noscroll').removeClass('scroll'); |
||||
return true; |
||||
} else { |
||||
$('html').addClass('scroll').removeClass('noscroll'); |
||||
return false; |
||||
} |
||||
}, |
||||
useIframe() { |
||||
const iframeEnabled = typeof RocketChat.iframeLogin !== 'undefined'; |
||||
return iframeEnabled && RocketChat.iframeLogin.reactiveEnabled.get(); |
||||
}, |
||||
iframeUrl() { |
||||
const iframeEnabled = typeof RocketChat.iframeLogin !== 'undefined'; |
||||
return iframeEnabled && RocketChat.iframeLogin.reactiveIframeUrl.get(); |
||||
}, |
||||
subsReady() { |
||||
const routerReady = FlowRouter.subsReady('userData', 'activeUsers'); |
||||
const subscriptionsReady = CachedChatSubscription.ready.get(); |
||||
const ready = (Meteor.userId() == null) || (routerReady && subscriptionsReady); |
||||
RocketChat.CachedCollectionManager.syncEnabled = ready; |
||||
return ready; |
||||
}, |
||||
hasUsername() { |
||||
return (Meteor.userId() != null) && (Meteor.user().username != null); |
||||
}, |
||||
requirePasswordChange() { |
||||
const user = Meteor.user(); |
||||
return user && user.requirePasswordChange === true; |
||||
}, |
||||
CustomScriptLoggedOut() { |
||||
const script = RocketChat.settings.get('Custom_Script_Logged_Out') || ''; |
||||
if (script.trim()) { |
||||
eval(script);//eslint-disable-line
|
||||
} |
||||
}, |
||||
CustomScriptLoggedIn() { |
||||
const script = RocketChat.settings.get('Custom_Script_Logged_In') || ''; |
||||
if (script.trim()) { |
||||
eval(script);//eslint-disable-line
|
||||
} |
||||
}, |
||||
embeddedVersion() { |
||||
if (RocketChat.Layout.isEmbedded()) { |
||||
return 'embedded-view'; |
||||
} |
||||
} |
||||
}); |
||||
|
||||
Template.main.events({ |
||||
'click .burger'() { |
||||
if (window.rocketDebug) { |
||||
console.log('room click .burger'); |
||||
} |
||||
return menu.toggle(); |
||||
}, |
||||
'touchstart'(e, t) { |
||||
if (document.body.clientWidth > 780) { |
||||
return; |
||||
} |
||||
t.touchstartX = undefined; |
||||
t.touchstartY = undefined; |
||||
t.movestarted = false; |
||||
t.blockmove = false; |
||||
t.isRtl = isRtl(localStorage.getItem('userLanguage')); |
||||
if ($(e.currentTarget).closest('.main-content').length > 0) { |
||||
t.touchstartX = e.originalEvent.touches[0].clientX; |
||||
t.touchstartY = e.originalEvent.touches[0].clientY; |
||||
t.mainContent = $('.main-content'); |
||||
return t.wrapper = $('.messages-box > .wrapper'); |
||||
} |
||||
}, |
||||
'touchmove'(e, t) { |
||||
if (t.touchstartX != null) { |
||||
const [touch] = e.originalEvent.touches; |
||||
const diffX = touch.clientX - t.touchstartX; |
||||
const diffY = touch.clientY - t.touchstartY; |
||||
const absX = Math.abs(diffX); |
||||
const absY = Math.abs(diffY); |
||||
if (t.movestarted !== true && t.blockmove !== true && absY > 5) { |
||||
t.blockmove = true; |
||||
} |
||||
if (t.blockmove !== true && (t.movestarted === true || absX > 5)) { |
||||
t.movestarted = true; |
||||
if (t.isRtl) { |
||||
if (menu.isOpen()) { |
||||
t.diff = -260 + diffX; |
||||
} else { |
||||
t.diff = diffX; |
||||
} |
||||
if (t.diff < -260) { |
||||
t.diff = -260; |
||||
} |
||||
if (t.diff > 0) { |
||||
t.diff = 0; |
||||
} |
||||
} else { |
||||
if (menu.isOpen()) { |
||||
t.diff = 260 + diffX; |
||||
} else { |
||||
t.diff = diffX; |
||||
} |
||||
if (t.diff > 260) { |
||||
t.diff = 260; |
||||
} |
||||
if (t.diff < 0) { |
||||
t.diff = 0; |
||||
} |
||||
} |
||||
t.mainContent.addClass('notransition'); |
||||
t.mainContent.css('transform', `translate(${ t.diff }px)`); |
||||
return t.wrapper.css('overflow', 'hidden'); |
||||
} |
||||
} |
||||
}, |
||||
'touchend'(e, t) { |
||||
if (t.movestarted === true) { |
||||
t.mainContent.removeClass('notransition'); |
||||
t.wrapper.css('overflow', ''); |
||||
if (t.isRtl) { |
||||
if (menu.isOpen()) { |
||||
if (t.diff >= -200) { |
||||
return menu.close(); |
||||
} else { |
||||
return menu.open(); |
||||
} |
||||
} else if (t.diff <= -60) { |
||||
return menu.open(); |
||||
} else { |
||||
return menu.close(); |
||||
} |
||||
} else if (menu.isOpen()) { |
||||
if (t.diff >= 200) { |
||||
return menu.open(); |
||||
} else { |
||||
return menu.close(); |
||||
} |
||||
} else if (t.diff >= 60) { |
||||
return menu.open(); |
||||
} else { |
||||
return menu.close(); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
|
||||
Template.main.onRendered(function() { |
||||
if (isRtl(localStorage.getItem('userLanguage'))) { |
||||
$('html').addClass('rtl'); |
||||
} else { |
||||
$('html').removeClass('rtl'); |
||||
} |
||||
$('#initial-page-loading').remove(); |
||||
window.addEventListener('focus', function() { |
||||
return Meteor.setTimeout(function() { |
||||
if (!$(':focus').is('INPUT,TEXTAREA')) { |
||||
return $('.input-message').focus(); |
||||
} |
||||
}, 100); |
||||
}); |
||||
return Tracker.autorun(function() { |
||||
swal.setDefaults({ |
||||
cancelButtonText: t('Cancel') |
||||
}); |
||||
const user = Meteor.user(); |
||||
const settings = user && user.settings; |
||||
const prefs = settings && settings.preferences; |
||||
if (prefs && prefs.hideUsernames != null) { |
||||
$(document.body).on('mouseleave', 'button.thumb', function() { |
||||
return RocketChat.tooltip.hide(); |
||||
}); |
||||
return $(document.body).on('mouseenter', 'button.thumb', function(e) { |
||||
const avatarElem = $(e.currentTarget); |
||||
const username = avatarElem.attr('data-username'); |
||||
if (username) { |
||||
e.stopPropagation(); |
||||
return RocketChat.tooltip.showElement($('<span>').text(username), avatarElem); |
||||
} |
||||
}); |
||||
} else { |
||||
$(document.body).off('mouseenter', 'button.thumb'); |
||||
return $(document.body).off('mouseleave', 'button.thumb'); |
||||
} |
||||
}); |
||||
}); |
||||
|
||||
Meteor.startup(function() { |
||||
return fireGlobalEvent('startup', true); |
||||
}); |
@ -1,47 +0,0 @@ |
||||
@VRecDialog = new class |
||||
opened: false |
||||
initiated: false |
||||
width: 400 |
||||
height: 280 |
||||
|
||||
init: -> |
||||
if @initiated |
||||
return |
||||
|
||||
@initiated = true |
||||
Blaze.render(Template.vrecDialog, document.body) |
||||
|
||||
open: (source) -> |
||||
if not @initiated |
||||
@init() |
||||
|
||||
@source = source |
||||
dialog = $('.vrec-dialog') |
||||
@setPosition(dialog, source) |
||||
dialog.addClass('show') |
||||
@opened = true |
||||
|
||||
@initializeCamera() |
||||
|
||||
close: -> |
||||
$('.vrec-dialog').removeClass('show') |
||||
@opened = false |
||||
|
||||
if @video? |
||||
VideoRecorder.stop() |
||||
|
||||
setPosition: (dialog, source) -> |
||||
sourcePos = $(source).offset() |
||||
left = sourcePos.left - @width + 100 |
||||
top = sourcePos.top - @height - 40 |
||||
|
||||
left = 10 if left < 0 |
||||
top = 10 if top < 0 |
||||
|
||||
dialog.css({ top: top + 'px', left: left + 'px' }) |
||||
|
||||
initializeCamera: -> |
||||
@video = $('.vrec-dialog video').get('0') |
||||
if not @video |
||||
return |
||||
VideoRecorder.start @video |
@ -0,0 +1,63 @@ |
||||
export const VRecDialog = new class { |
||||
static initClass() { |
||||
this.prototype.opened = false; |
||||
this.prototype.initiated = false; |
||||
this.prototype.width = 400; |
||||
this.prototype.height = 280; |
||||
} |
||||
|
||||
init() { |
||||
if (this.initiated) { |
||||
return; |
||||
} |
||||
|
||||
this.initiated = true; |
||||
return Blaze.render(Template.vrecDialog, document.body); |
||||
} |
||||
|
||||
open(source) { |
||||
if (!this.initiated) { |
||||
this.init(); |
||||
} |
||||
|
||||
this.source = source; |
||||
const dialog = $('.vrec-dialog'); |
||||
this.setPosition(dialog, source); |
||||
dialog.addClass('show'); |
||||
this.opened = true; |
||||
|
||||
return this.initializeCamera(); |
||||
} |
||||
|
||||
close() { |
||||
$('.vrec-dialog').removeClass('show'); |
||||
this.opened = false; |
||||
|
||||
if (this.video != null) { |
||||
return VideoRecorder.stop(); |
||||
} |
||||
} |
||||
|
||||
setPosition(dialog, source) { |
||||
const sourcePos = $(source).offset(); |
||||
let left = (sourcePos.left - this.width) + 100; |
||||
let top = sourcePos.top - this.height - 40; |
||||
|
||||
if (left < 0) { |
||||
left = 10; |
||||
} |
||||
if (top < 0) { |
||||
top = 10; |
||||
} |
||||
|
||||
return dialog.css({ top: `${ top }px`, left: `${ left }px` }); |
||||
} |
||||
|
||||
initializeCamera() { |
||||
this.video = $('.vrec-dialog video').get('0'); |
||||
if (!this.video) { |
||||
return; |
||||
} |
||||
return VideoRecorder.start(this.video); |
||||
} |
||||
}; |
@ -1,6 +0,0 @@ |
||||
Template.roomNotFound.helpers |
||||
data: -> |
||||
return Session.get 'roomNotFound' |
||||
|
||||
name: -> |
||||
return Blaze._escape(this.name) |
@ -0,0 +1,8 @@ |
||||
Template.roomNotFound.helpers({ |
||||
data() { |
||||
return Session.get('roomNotFound'); |
||||
}, |
||||
name() { |
||||
return Blaze._escape(this.name); |
||||
} |
||||
}); |
@ -1,5 +0,0 @@ |
||||
Template.burger.helpers |
||||
unread: -> |
||||
return Session.get 'unread' |
||||
isMenuOpen: -> |
||||
if Session.equals('isMenuOpen', true) then 'menu-opened' |
@ -0,0 +1,10 @@ |
||||
Template.burger.helpers({ |
||||
unread() { |
||||
return Session.get('unread'); |
||||
}, |
||||
isMenuOpen() { |
||||
if (Session.equals('isMenuOpen', true)) { |
||||
return 'menu-opened'; |
||||
} |
||||
} |
||||
}); |
@ -1,5 +0,0 @@ |
||||
Template.home.helpers |
||||
title: -> |
||||
return RocketChat.settings.get 'Layout_Home_Title' |
||||
body: -> |
||||
return RocketChat.settings.get 'Layout_Home_Body' |
@ -0,0 +1,8 @@ |
||||
Template.home.helpers({ |
||||
title() { |
||||
return RocketChat.settings.get('Layout_Home_Title'); |
||||
}, |
||||
body() { |
||||
return RocketChat.settings.get('Layout_Home_Body'); |
||||
} |
||||
}); |
@ -1,10 +0,0 @@ |
||||
Template.roomSearch.helpers |
||||
roomIcon: -> |
||||
return 'icon-at' if this.type is 'u' |
||||
|
||||
if this.type is 'r' |
||||
return RocketChat.roomTypes.getIcon this.t |
||||
|
||||
userStatus: -> |
||||
if this.type is 'u' |
||||
return 'status-' + this.status |
@ -0,0 +1,15 @@ |
||||
Template.roomSearch.helpers({ |
||||
roomIcon() { |
||||
if (this.type === 'u') { |
||||
return 'icon-at'; |
||||
} |
||||
if (this.type === 'r') { |
||||
return RocketChat.roomTypes.getIcon(this.t); |
||||
} |
||||
}, |
||||
userStatus() { |
||||
if (this.type === 'u') { |
||||
return `status-${ this.status }`; |
||||
} |
||||
} |
||||
}); |
@ -1,23 +0,0 @@ |
||||
Template.secretURL.helpers |
||||
registrationAllowed: -> |
||||
return RocketChat.settings.get('Accounts_RegistrationForm') is 'Secret URL' and Template.instance().hashIsValid?.get() |
||||
|
||||
ready: -> |
||||
return Template.instance().subscriptionsReady?() and Template.instance().hashReady?.get() |
||||
|
||||
|
||||
Template.secretURL.onCreated -> |
||||
@hashIsValid = new ReactiveVar false |
||||
@hashReady = new ReactiveVar false |
||||
|
||||
Meteor.call 'checkRegistrationSecretURL', FlowRouter.getParam('hash'), (err, success) => |
||||
@hashReady.set true |
||||
if success |
||||
Session.set 'loginDefaultState', 'register' |
||||
KonchatNotification.getDesktopPermission() |
||||
@hashIsValid.set true |
||||
else |
||||
@hashIsValid.set false |
||||
|
||||
Template.secretURL.onRendered -> |
||||
$('#initial-page-loading').remove() |
@ -0,0 +1,29 @@ |
||||
/* globals KonchatNotification */ |
||||
Template.secretURL.helpers({ |
||||
registrationAllowed() { |
||||
const {hashIsValid} = Template.instance(); |
||||
return RocketChat.settings.get('Accounts_RegistrationForm') === 'Secret URL' && hashIsValid && hashIsValid.get(); |
||||
}, |
||||
ready() { |
||||
const {subscriptionsReady, hashReady} = Template.instance(); |
||||
return typeof subscriptionsReady === 'function' && subscriptionsReady() && hashReady && hashReady.get(); |
||||
} |
||||
}); |
||||
|
||||
Template.secretURL.onCreated(function() { |
||||
this.hashIsValid = new ReactiveVar(false); |
||||
this.hashReady = new ReactiveVar(false); |
||||
Meteor.call('checkRegistrationSecretURL', FlowRouter.getParam('hash'), (err, success) => { |
||||
this.hashReady.set(true); |
||||
if (success) { |
||||
Session.set('loginDefaultState', 'register'); |
||||
KonchatNotification.getDesktopPermission(); |
||||
return this.hashIsValid.set(true); |
||||
} |
||||
return this.hashIsValid.set(false); |
||||
}); |
||||
}); |
||||
|
||||
Template.secretURL.onRendered(function() { |
||||
return $('#initial-page-loading').remove(); |
||||
}); |
@ -1,16 +0,0 @@ |
||||
Template.cmsPage.onCreated -> |
||||
@page = new ReactiveVar '' |
||||
Meteor.autorun => |
||||
if Session.get('cmsPage')? |
||||
@page.set RocketChat.settings.get Session.get('cmsPage') |
||||
|
||||
Template.cmsPage.helpers |
||||
page: -> |
||||
return Template.instance().page.get() |
||||
|
||||
Template.cmsPage.events |
||||
'click .cms-page-close': -> |
||||
FlowRouter.go('/') |
||||
|
||||
Template.cmsPage.onRendered -> |
||||
$('#initial-page-loading').remove() |
@ -0,0 +1,25 @@ |
||||
Template.cmsPage.onCreated(function() { |
||||
this.page = new ReactiveVar(''); |
||||
return Meteor.autorun(() => { |
||||
const cmsPage = Session.get('cmsPage'); |
||||
if (cmsPage != null) { |
||||
return this.page.set(RocketChat.settings.get(cmsPage)); |
||||
} |
||||
}); |
||||
}); |
||||
|
||||
Template.cmsPage.helpers({ |
||||
page() { |
||||
return Template.instance().page.get(); |
||||
} |
||||
}); |
||||
|
||||
Template.cmsPage.events({ |
||||
'click .cms-page-close'() { |
||||
return FlowRouter.go('/'); |
||||
} |
||||
}); |
||||
|
||||
Template.cmsPage.onRendered(function() { |
||||
return $('#initial-page-loading').remove(); |
||||
}); |
@ -1,20 +0,0 @@ |
||||
Template.fxOsInstallPrompt.onRendered -> |
||||
showPrompt = () -> |
||||
request = window.navigator.mozApps.install 'http://' + location.host + '/manifest.webapp' |
||||
request.onsuccess = () -> |
||||
# Save the App object that is returned |
||||
appRecord = this.result |
||||
BlazeLayout.render 'fxOsInstallDone' |
||||
|
||||
request.onerror = () -> |
||||
# Display the error information from the DOMError object |
||||
BlazeLayout.render 'fxOsInstallError', {installError: this.error.name} |
||||
|
||||
setTimeout(showPrompt, 2000); |
||||
$('#initial-page-loading').remove() |
||||
|
||||
Template.fxOsInstallDone.onRendered -> |
||||
$('#initial-page-loading').remove() |
||||
|
||||
Template.fxOsInstallError.onRendered -> |
||||
$('#initial-page-loading').remove() |
@ -0,0 +1,19 @@ |
||||
Template.fxOsInstallPrompt.onRendered(function() { |
||||
|
||||
const showPrompt = function() { |
||||
const request = window.navigator.mozApps.install(`http://${ location.host }/manifest.webapp`); |
||||
request.onsuccess = function() { |
||||
BlazeLayout.render('fxOsInstallDone'); |
||||
}; |
||||
request.onerror = function() { |
||||
BlazeLayout.render('fxOsInstallError', { |
||||
installError: this.error.name |
||||
}); |
||||
}; |
||||
}; |
||||
setTimeout(showPrompt, 2000); |
||||
return $('#initial-page-loading').remove(); |
||||
}); |
||||
|
||||
Template.fxOsInstallDone.onRendered(() => $('#initial-page-loading').remove()); |
||||
Template.fxOsInstallError.onRendered(() => $('#initial-page-loading').remove()); |
@ -1 +0,0 @@ |
||||
Template.modal.rendered = -> |
@ -0,0 +1 @@ |
||||
Template.modal.rendered = function() {}; |
@ -1,19 +0,0 @@ |
||||
@getAvatarUrlFromUsername = (username) -> |
||||
key = "avatar_random_#{username}" |
||||
random = Session?.keys[key] or 0 |
||||
|
||||
if not username? |
||||
return |
||||
|
||||
cdnPrefix = (RocketChat.settings.get('CDN_PREFIX') or '').trim().replace(/\/$/, '') |
||||
pathPrefix = (__meteor_runtime_config__.ROOT_URL_PATH_PREFIX or '').trim().replace(/\/$/, '') |
||||
|
||||
if cdnPrefix |
||||
path = cdnPrefix + pathPrefix |
||||
else if Meteor.isCordova |
||||
# Meteor.absoluteUrl alread has path prefix |
||||
path = Meteor.absoluteUrl().replace(/\/$/, '') |
||||
else |
||||
path = pathPrefix |
||||
|
||||
return "#{path}/avatar/#{encodeURIComponent(username)}?_dc=#{random}" |
@ -0,0 +1,17 @@ |
||||
// TODO: remove global
|
||||
this.getAvatarUrlFromUsername = function(username) { |
||||
const key = `avatar_random_${ username }`; |
||||
const random = typeof Session !== 'undefined' ? Session.keys[key] : 0; |
||||
if (username == null) { |
||||
return; |
||||
} |
||||
const cdnPrefix = (RocketChat.settings.get('CDN_PREFIX') || '').trim().replace(/\/$/, ''); |
||||
const pathPrefix = (__meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '').trim().replace(/\/$/, ''); |
||||
let path = pathPrefix; |
||||
if (cdnPrefix) { |
||||
path = cdnPrefix + pathPrefix; |
||||
} else if (Meteor.isCordova) { |
||||
path = Meteor.absoluteUrl().replace(/\/$/, ''); |
||||
} |
||||
return `${ path }/avatar/${ encodeURIComponent(username) }?_dc=${ random }`; |
||||
}; |
@ -1,62 +0,0 @@ |
||||
exec = Npm.require('child_process').exec |
||||
os = Npm.require('os') |
||||
Future = Npm.require('fibers/future') |
||||
async = Npm.require('async') |
||||
|
||||
Plugin.registerCompiler |
||||
extensions: ['info'] |
||||
, -> new VersionCompiler() |
||||
|
||||
|
||||
class VersionCompiler |
||||
processFilesForTarget: (files) -> |
||||
future = new Future |
||||
|
||||
processFile = (file, cb) -> |
||||
return cb() if not file.getDisplayPath().match /rocketchat\.info$/ |
||||
|
||||
output = JSON.parse file.getContentsAsString() |
||||
output.build = |
||||
date: new Date().toISOString() |
||||
nodeVersion: process.version |
||||
arch: process.arch |
||||
platform: process.platform |
||||
osRelease: os.release() |
||||
totalMemory: os.totalmem() |
||||
freeMemory: os.freemem() |
||||
cpus: os.cpus().length |
||||
|
||||
if process.env.TRAVIS_BUILD_NUMBER |
||||
output.travis = |
||||
buildNumber: process.env.TRAVIS_BUILD_NUMBER |
||||
branch: process.env.TRAVIS_BRANCH |
||||
tag: process.env.TRAVIS_TAG |
||||
|
||||
exec "git log --pretty=format:'%H%n%ad%n%an%n%s' -n 1", (err, result) -> |
||||
if not err? |
||||
result = result.split('\n') |
||||
|
||||
output.commit = |
||||
hash: result.shift() |
||||
date: result.shift() |
||||
author: result.shift() |
||||
subject: result.join('\n') |
||||
|
||||
exec "git describe --abbrev=0 --tags", (err, result) -> |
||||
if not err? |
||||
output.commit?.tag = result.replace('\n', '') |
||||
|
||||
exec "git rev-parse --abbrev-ref HEAD", (err, result) -> |
||||
if not err? |
||||
output.commit?.branch = result.replace('\n', '') |
||||
|
||||
output = """ |
||||
RocketChat.Info = #{JSON.stringify(output, null, 4)}; |
||||
""" |
||||
|
||||
file.addJavaScript({ data: output, path: file.getPathInPackage() + '.js' }) |
||||
cb() |
||||
|
||||
async.each files, processFile, future.resolver() |
||||
|
||||
future.wait() |
@ -0,0 +1,74 @@ |
||||
import {exec} from 'child_process'; |
||||
import os from 'os'; |
||||
import Future from 'fibers/future'; |
||||
import async from 'async'; |
||||
|
||||
class VersionCompiler { |
||||
processFilesForTarget(files) { |
||||
const future = new Future; |
||||
const processFile = function(file, cb) { |
||||
if (!file.getDisplayPath().match(/rocketchat\.info$/)) { |
||||
return cb(); |
||||
} |
||||
|
||||
let output = JSON.parse(file.getContentsAsString()); |
||||
output.build = { |
||||
date: new Date().toISOString(), |
||||
nodeVersion: process.version, |
||||
arch: process.arch, |
||||
platform: process.platform, |
||||
osRelease: os.release(), |
||||
totalMemory: os.totalmem(), |
||||
freeMemory: os.freemem(), |
||||
cpus: os.cpus().length |
||||
}; |
||||
|
||||
if (process.env.TRAVIS_BUILD_NUMBER) { |
||||
output.travis = { |
||||
buildNumber: process.env.TRAVIS_BUILD_NUMBER, |
||||
branch: process.env.TRAVIS_BRANCH, |
||||
tag: process.env.TRAVIS_TAG |
||||
}; |
||||
} |
||||
|
||||
exec('git log --pretty=format:\'%H%n%ad%n%an%n%s\' -n 1', function(err, result) { |
||||
if (err == null) { |
||||
result = result.split('\n'); |
||||
output.commit = { |
||||
hash: result.shift(), |
||||
date: result.shift(), |
||||
author: result.shift(), |
||||
subject: result.join('\n') |
||||
}; |
||||
} |
||||
|
||||
exec('git describe --abbrev=0 --tags', function(err, result) { |
||||
if (err == null && output.commit != null) { |
||||
output.commit.tag = result.replace('\n', ''); |
||||
} |
||||
|
||||
exec('git rev-parse --abbrev-ref HEAD', function(err, result) { |
||||
if (err == null && output.commit != null) { |
||||
output.commit.branch = result.replace('\n', ''); |
||||
} |
||||
output = `RocketChat.Info = ${ JSON.stringify(output, null, 4) };`; |
||||
file.addJavaScript({ |
||||
data: output, |
||||
path: `${ file.getPathInPackage() }.js` |
||||
}); |
||||
cb(); |
||||
}); |
||||
}); |
||||
}); |
||||
}; |
||||
|
||||
async.each(files, processFile, future.resolver()); |
||||
return future.wait(); |
||||
} |
||||
} |
||||
|
||||
Plugin.registerCompiler({ |
||||
extensions: ['info'] |
||||
}, function() { |
||||
return new VersionCompiler(); |
||||
}); |
@ -1,20 +0,0 @@ |
||||
config = |
||||
serverURL: '' |
||||
identityPath: '/oauth/me' |
||||
addAutopublishFields: |
||||
forLoggedInUser: ['services.wordpress'] |
||||
forOtherUsers: ['services.wordpress.user_login'] |
||||
|
||||
WordPress = new CustomOAuth 'wordpress', config |
||||
|
||||
if Meteor.isServer |
||||
Meteor.startup -> |
||||
RocketChat.settings.get 'API_Wordpress_URL', (key, value) -> |
||||
config.serverURL = value |
||||
WordPress.configure config |
||||
else |
||||
Meteor.startup -> |
||||
Tracker.autorun -> |
||||
if RocketChat.settings.get 'API_Wordpress_URL' |
||||
config.serverURL = RocketChat.settings.get 'API_Wordpress_URL' |
||||
WordPress.configure config |
@ -0,0 +1,30 @@ |
||||
/* globals CustomOAuth */ |
||||
|
||||
const config = { |
||||
serverURL: '', |
||||
identityPath: '/oauth/me', |
||||
addAutopublishFields: { |
||||
forLoggedInUser: ['services.wordpress'], |
||||
forOtherUsers: ['services.wordpress.user_login'] |
||||
} |
||||
}; |
||||
|
||||
const WordPress = new CustomOAuth('wordpress', config); |
||||
|
||||
if (Meteor.isServer) { |
||||
Meteor.startup(function() { |
||||
return RocketChat.settings.get('API_Wordpress_URL', function(key, value) { |
||||
config.serverURL = value; |
||||
return WordPress.configure(config); |
||||
}); |
||||
}); |
||||
} else { |
||||
Meteor.startup(function() { |
||||
return Tracker.autorun(function() { |
||||
if (RocketChat.settings.get('API_Wordpress_URL')) { |
||||
config.serverURL = RocketChat.settings.get('API_Wordpress_URL'); |
||||
return WordPress.configure(config); |
||||
} |
||||
}); |
||||
}); |
||||
} |
@ -1,9 +0,0 @@ |
||||
RocketChat.settings.addGroup 'OAuth', -> |
||||
@section 'WordPress', -> |
||||
enableQuery = {_id: 'Accounts_OAuth_Wordpress', value: true} |
||||
@add 'Accounts_OAuth_Wordpress', false, { type: 'boolean', public: true } |
||||
@add 'API_Wordpress_URL', '', { type: 'string', enableQuery: enableQuery, public: true } |
||||
@add 'Accounts_OAuth_Wordpress_id', '', { type: 'string', enableQuery: enableQuery } |
||||
@add 'Accounts_OAuth_Wordpress_secret', '', { type: 'string', enableQuery: enableQuery } |
||||
@add 'Accounts_OAuth_Wordpress_callback_url', '_oauth/wordpress', { type: 'relativeUrl', readonly: true, force: true, enableQuery: enableQuery } |
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue