Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat into rocketchat-ui-message

pull/6914/head
Guilherme Gazzo 8 years ago
commit 6ac7193519
  1. 4
      .docker/develop/Dockerfile
  2. 4
      .docker/latest/Dockerfile
  3. 37
      .docker/release-candidate/Dockerfile
  4. 116
      .github/changelog.js
  5. 40
      .github/templates/commit.hbs
  6. 11
      .github/templates/footer.hbs
  7. 26
      .github/templates/header.hbs
  8. 22
      .github/templates/template.hbs
  9. 38
      .meteor/packages
  10. 2
      .meteor/release
  11. 81
      .meteor/versions
  12. 2
      .sandstorm/sandstorm-pkgdef.capnp
  13. 47
      .scripts/version.js
  14. 61
      .snapcraft/README.md
  15. 102
      .snapcraft/candidate/snapcraft.yaml
  16. 54
      .snapcraft/edge/snapcraft.yaml
  17. 6
      .snapcraft/resources/initmongo
  18. 8
      .snapcraft/resources/initmongoreplset.js
  19. 13
      .snapcraft/resources/initreplset.js
  20. 36
      .snapcraft/resources/preparecaddy
  21. 22
      .snapcraft/resources/preparemongo
  22. 72
      .snapcraft/resources/restoredb
  23. 43
      .snapcraft/resources/startRocketChat
  24. 8
      .snapcraft/resources/startmongo
  25. 54
      .snapcraft/stable/snapcraft.yaml
  26. 2
      .stylelintignore
  27. 3
      .stylelintrc
  28. 4
      .travis.yml
  29. 12
      .travis/snap.sh
  30. 215
      HISTORY.md
  31. 8
      README.md
  32. 4
      app.json
  33. 22
      client/notifications/UsersNameChanged.js
  34. 2
      client/routes/router.js
  35. 2
      client/startup/unread.js
  36. 4
      docker-compose.yml
  37. 23
      package.json
  38. 1
      packages/rocketchat-api/package.js
  39. 63
      packages/rocketchat-api/server/v1/channels.js
  40. 2
      packages/rocketchat-api/server/v1/groups.js
  41. 2
      packages/rocketchat-api/server/v1/helpers/getUserFromParams.js
  42. 5
      packages/rocketchat-api/server/v1/helpers/isUserFromParams.js
  43. 23
      packages/rocketchat-api/server/v1/integrations.js
  44. 56
      packages/rocketchat-api/server/v1/users.js
  45. 4
      packages/rocketchat-authorization/client/lib/ChatPermissions.js
  46. 16
      packages/rocketchat-authorization/server/functions/canAccessRoom.js
  47. 2
      packages/rocketchat-authorization/server/methods/addUserToRole.js
  48. 14
      packages/rocketchat-authorization/server/startup.js
  49. 2
      packages/rocketchat-channel-settings/client/lib/ChannelSettings.js
  50. 59
      packages/rocketchat-channel-settings/client/startup/messageTypes.js
  51. 1
      packages/rocketchat-channel-settings/client/startup/tabBar.js
  52. 4
      packages/rocketchat-custom-oauth/custom_oauth_client.js
  53. 38
      packages/rocketchat-custom-oauth/custom_oauth_server.js
  54. 23
      packages/rocketchat-drupal/README.md
  55. 39
      packages/rocketchat-drupal/common.js
  56. 11
      packages/rocketchat-drupal/login-button.css
  57. 22
      packages/rocketchat-drupal/package.js
  58. 14
      packages/rocketchat-drupal/startup.js
  59. 14
      packages/rocketchat-emoji-custom/client/lib/emojiCustom.js
  60. 18
      packages/rocketchat-emoji/emojiPicker.js
  61. 10
      packages/rocketchat-emoji/emojiPicker.less
  62. 17
      packages/rocketchat-emoji/lesshat.less
  63. 38
      packages/rocketchat-emoji/lib/EmojiPicker.js
  64. 743
      packages/rocketchat-google-natural-language/.npm/package/npm-shrinkwrap.json
  65. 10
      packages/rocketchat-i18n/i18n/bg.i18n.json
  66. 26
      packages/rocketchat-i18n/i18n/ca.i18n.json
  67. 42
      packages/rocketchat-i18n/i18n/cs.i18n.json
  68. 1
      packages/rocketchat-i18n/i18n/de-AT.i18n.json
  69. 37
      packages/rocketchat-i18n/i18n/de.i18n.json
  70. 7
      packages/rocketchat-i18n/i18n/el.i18n.json
  71. 32
      packages/rocketchat-i18n/i18n/en.i18n.json
  72. 14
      packages/rocketchat-i18n/i18n/es.i18n.json
  73. 472
      packages/rocketchat-i18n/i18n/fr.i18n.json
  74. 1
      packages/rocketchat-i18n/i18n/he.i18n.json
  75. 1
      packages/rocketchat-i18n/i18n/hr.i18n.json
  76. 9
      packages/rocketchat-i18n/i18n/it.i18n.json
  77. 1
      packages/rocketchat-i18n/i18n/ja.i18n.json
  78. 42
      packages/rocketchat-i18n/i18n/ko.i18n.json
  79. 1
      packages/rocketchat-i18n/i18n/pl.i18n.json
  80. 4
      packages/rocketchat-i18n/i18n/sv.i18n.json
  81. 1
      packages/rocketchat-i18n/i18n/zh.i18n.json
  82. 6
      packages/rocketchat-importer-csv/server.js
  83. 2
      packages/rocketchat-integrations/client/views/integrationsIncoming.js
  84. 8
      packages/rocketchat-integrations/client/views/integrationsOutgoing.html
  85. 11
      packages/rocketchat-integrations/client/views/integrationsOutgoing.js
  86. 12
      packages/rocketchat-integrations/server/api/api.js
  87. 9
      packages/rocketchat-integrations/server/lib/triggerHandler.js
  88. 5
      packages/rocketchat-integrations/server/lib/validation.js
  89. 1
      packages/rocketchat-integrations/server/methods/outgoing/updateOutgoingIntegration.js
  90. 181
      packages/rocketchat-katex/katex.coffee
  91. 255
      packages/rocketchat-katex/katex.js
  92. 5
      packages/rocketchat-katex/package.js
  93. 6
      packages/rocketchat-katex/settings.coffee
  94. 32
      packages/rocketchat-katex/settings.js
  95. 6
      packages/rocketchat-lib/client/MessageAction.js
  96. 2
      packages/rocketchat-lib/client/lib/cachedCollection.js
  97. 9
      packages/rocketchat-lib/client/lib/openRoom.coffee
  98. 98
      packages/rocketchat-lib/client/lib/openRoom.js
  99. 2
      packages/rocketchat-lib/client/lib/roomExit.js
  100. 87
      packages/rocketchat-lib/client/lib/roomTypes.coffee
  101. Some files were not shown because too many files have changed in this diff Show More

@ -24,7 +24,9 @@ VOLUME /app/uploads
WORKDIR /app/bundle
# needs a mongoinstance - defaults to container linking with alias 'mongo'
ENV MONGO_URL=mongodb://mongo:27017/rocketchat \
ENV DEPLOY_METHOD=docker \
NODE_ENV=production \
MONGO_URL=mongodb://mongo:27017/rocketchat \
MONGO_OPLOG_URL=mongodb://mongo:27017/local \
HOME=/tmp \
PORT=3000 \

@ -24,7 +24,9 @@ VOLUME /app/uploads
WORKDIR /app/bundle
# needs a mongoinstance - defaults to container linking with alias 'mongo'
ENV MONGO_URL=mongodb://mongo:27017/rocketchat \
ENV DEPLOY_METHOD=docker \
NODE_ENV=production \
MONGO_URL=mongodb://mongo:27017/rocketchat \
HOME=/tmp \
PORT=3000 \
ROOT_URL=http://localhost:3000 \

@ -0,0 +1,37 @@
FROM rocketchat/base:4
ENV RC_VERSION release-candidate
MAINTAINER buildmaster@rocket.chat
RUN set -x \
&& curl -SLf "https://rocket.chat/releases/${RC_VERSION}/download" -o rocket.chat.tgz \
&& curl -SLf "https://rocket.chat/releases/${RC_VERSION}/asc" -o rocket.chat.tgz.asc \
&& mkdir /app \
&& gpg --verify rocket.chat.tgz.asc \
&& mkdir -p /app \
&& tar -zxf rocket.chat.tgz -C /app \
&& rm rocket.chat.tgz rocket.chat.tgz.asc \
&& cd /app/bundle/programs/server \
&& npm install \
&& npm cache clear \
&& chown -R rocketchat:rocketchat /app
USER rocketchat
VOLUME /app/uploads
WORKDIR /app/bundle
# needs a mongoinstance - defaults to container linking with alias 'mongo'
ENV DEPLOY_METHOD=docker \
NODE_ENV=production \
MONGO_URL=mongodb://mongo:27017/rocketchat \
HOME=/tmp \
PORT=3000 \
ROOT_URL=http://localhost:3000 \
Accounts_AvatarStorePath=/app/uploads
EXPOSE 3000
CMD ["node", "main.js"]

@ -0,0 +1,116 @@
/* eslint no-var: 0, object-shorthand: 0, prefer-template: 0 */
'use strict';
var readFile = require('fs').readFileSync;
var resolve = require('path').resolve;
var gitUrl = 'https://github.com/RocketChat/Rocket.Chat';
var parserOpts = {
headerPattern: /^(\[([A-z]+)\] )?(.*)$/m,
headerCorrespondence: [
'stype',
'type',
'subject'
],
mergePattern: /^Merge pull request #(.*) from .*$/,
mergeCorrespondence: ['pr']
// noteKeywords: ['BREAKING CHANGE', 'BREAKING CHANGES'],
// revertPattern: /^revert:\s([\s\S]*?)\s*This reverts commit (\w*)\./,
// revertCorrespondence: ['header', 'hash'],
// mergePattern: /^Merge pull request #(\d+) from (.*)$/,
// mergeCorrespondence: ['id', 'source']
};
var LABELS = {
BREAK: {
title: 'BREAKING CHANGES',
collapse: false
},
NEW: {
title: 'New Features',
collapse: false
},
FIX: {
title: 'Bug Fixes',
collapse: false
},
DOC: {
title: 'Documentation',
collapse: true
},
OTHER: {
title: 'Others',
collapse: true
}
};
var sort = Object.keys(LABELS);
var writerOpts = {
transform: function(commit) {
if (!commit.pr) {
return;
}
// console.log(commit);
commit.type = (commit.type || 'OTHER').toUpperCase();
if (LABELS[commit.type] == null) {
return;
}
commit.pr_url = gitUrl + '/pull/' + commit.pr;
var issues = [];
if (typeof commit.hash === 'string') {
commit.hash = commit.hash.substring(0, 7);
}
if (typeof commit.subject === 'string') {
// GitHub issue URLs.
commit.subject = commit.subject.replace(/#([0-9]+)/g, function(_, issue) {
issues.push(issue);
return '[#' + issue + '](' + gitUrl + '/issue/' + issue + ')';
});
// GitHub user URLs.
commit.subject = commit.subject.replace(/@([a-zA-Z0-9_]+)/g, '[@$1](https://github.com/$1)');
}
// remove references that already appear in the subject
commit.references = commit.references.filter(function(reference) {
if (issues.indexOf(reference.issue) === -1) {
return true;
}
return false;
});
return commit;
},
groupBy: 'type',
commitGroupsSort: function(a, b) {
return sort.indexOf(a.title) > sort.indexOf(b.title);
},
finalizeContext: function(context) {
context.commitGroups.forEach(function(group) {
Object.assign(group, LABELS[group.title.toUpperCase()]);
});
// console.log(context);
return context;
},
commitsSort: ['subject']
};
writerOpts.mainTemplate = readFile(resolve(__dirname, 'templates/template.hbs'), 'utf-8');
writerOpts.headerPartial = readFile(resolve(__dirname, 'templates/header.hbs'), 'utf-8');
writerOpts.commitPartial = readFile(resolve(__dirname, 'templates/commit.hbs'), 'utf-8');
writerOpts.footerPartial = readFile(resolve(__dirname, 'templates/footer.hbs'), 'utf-8');
module.exports = {
gitRawCommitsOpts: {
merges: null
},
parserOpts: parserOpts,
writerOpts: writerOpts
};

@ -0,0 +1,40 @@
{{!-- pr reference --}}- {{#if pr}}[#{{pr}}]({{pr_url}}){{/if}}
{{~!-- subject --}} {{subject}}
{{~!-- commit references --}}
{{~#if references~}}
, closes
{{~#each references}} {{#if @root.linkReferences~}}
[
{{~#if this.owner}}
{{~this.owner}}/
{{~/if}}
{{~this.repository}}#{{this.issue}}](
{{~#if @root.repository}}
{{~#if @root.host}}
{{~@root.host}}/
{{~/if}}
{{~#if this.repository}}
{{~#if this.owner}}
{{~this.owner}}/
{{~/if}}
{{~this.repository}}
{{~else}}
{{~#if @root.owner}}
{{~@root.owner}}/
{{~/if}}
{{~@root.repository}}
{{~/if}}
{{~else}}
{{~@root.repoUrl}}
{{~/if}}/
{{~@root.issue}}/{{this.issue}})
{{~else}}
{{~#if this.owner}}
{{~this.owner}}/
{{~/if}}
{{~this.repository}}#{{this.issue}}
{{~/if}}{{/each}}
{{~/if}}

@ -0,0 +1,11 @@
{{#if noteGroups}}
{{#each noteGroups}}
### {{title}}
{{#each notes}}
* {{#if commit.scope}}**{{commit.scope}}:** {{/if}}{{text}}
{{/each}}
{{/each}}
{{/if}}

@ -0,0 +1,26 @@
<a name="{{version}}"></a>
{{#if isPatch~}}
##
{{~else~}}
#
{{~/if}} {{#if @root.linkCompare~}}
[{{version}}](
{{~#if @root.repository~}}
{{~#if @root.host}}
{{~@root.host}}/
{{~/if}}
{{~#if @root.owner}}
{{~@root.owner}}/
{{~/if}}
{{~@root.repository}}
{{~else}}
{{~@root.repoUrl}}
{{~/if~}}
/compare/{{previousTag}}...{{currentTag}})
{{~else}}
{{~version}}
{{~/if}}
{{~#if title}} "{{title}}"
{{~/if}}
{{~#if date}} ({{date}})
{{/if}}

@ -0,0 +1,22 @@
{{> header}}
{{#each commitGroups}}
{{#if collapse}}
<details>
<summary>{{title}}</summary>
{{else}}
### {{title}}
{{/if}}
{{#each commits}}
{{> commit root=@root}}
{{/each}}
{{#if collapse}}
</details>
{{/if}}
{{/each}}
{{> footer}}

@ -4,39 +4,39 @@
# but you can also edit it by hand.
rocketchat:cors
accounts-facebook@1.1.0
accounts-github@1.2.0
accounts-google@1.1.0
accounts-meteor-developer@1.2.0
accounts-password@1.3.4
accounts-twitter@1.2.0
accounts-facebook@1.1.1
accounts-github@1.2.1
accounts-google@1.1.2
accounts-meteor-developer@1.2.1
accounts-password@1.3.6
accounts-twitter@1.2.1
blaze-html-templates
check@1.2.4
check@1.2.5
coffeescript@1.11.1_4
ddp-rate-limiter@1.0.6
ecmascript@0.6.3
ddp-rate-limiter@1.0.7
ecmascript@0.7.3
ejson@1.0.13
email@1.1.18
email@1.2.1
fastclick@1.0.13
http@1.2.11
http@1.2.12
jquery@1.11.10
less@2.7.9
logging@1.1.17
meteor-base@1.0.4
mobile-experience@1.0.4
mongo@1.1.15
mongo@1.1.17
random@1.0.10
rate-limit@1.0.6
rate-limit@1.0.8
reactive-dict@1.1.8
reactive-var@1.0.11
reload@1.1.11
service-configuration@1.0.11
session@1.1.7
shell-server@0.2.2
shell-server@0.2.3
spacebars
standard-minifier-css@1.3.3
standard-minifier-js@1.2.2
tracker@1.1.2
standard-minifier-css@1.3.4
standard-minifier-js@2.0.0
tracker@1.1.3
rocketchat:2fa
rocketchat:action-links
@ -132,6 +132,9 @@ rocketchat:videobridge
rocketchat:webrtc
rocketchat:wordpress
rocketchat:message-snippet
rocketchat:google-natural-language
rocketchat:drupal
rocketchat:monitoring
#rocketchat:chatops
konecty:change-case
@ -169,4 +172,3 @@ underscorestring:underscore.string
yasaricli:slugify
yasinuslu:blaze-meta
deepwell:bootstrap-datepicker2
rocketchat:google-natural-language

@ -1 +1 @@
METEOR@1.4.3.1
METEOR@1.4.4.2

@ -1,58 +1,58 @@
accounts-base@1.2.14
accounts-facebook@1.1.0
accounts-github@1.2.0
accounts-google@1.1.0
accounts-meteor-developer@1.2.0
accounts-base@1.2.17
accounts-facebook@1.1.1
accounts-github@1.2.1
accounts-google@1.1.2
accounts-meteor-developer@1.2.1
accounts-oauth@1.1.15
accounts-password@1.3.4
accounts-twitter@1.2.0
accounts-password@1.3.6
accounts-twitter@1.2.1
aldeed:simple-schema@1.5.3
allow-deny@1.0.5
autoupdate@1.3.12
babel-compiler@6.14.1
babel-compiler@6.18.2
babel-runtime@1.0.1
base64@1.0.10
binary-heap@1.0.10
blaze@2.3.0
blaze-html-templates@1.1.0
blaze@2.3.2
blaze-html-templates@1.1.2
blaze-tools@1.0.10
boilerplate-generator@1.0.11
caching-compiler@1.1.9
caching-html-compiler@1.1.0
caching-html-compiler@1.1.2
callback-hook@1.0.10
cfs:http-methods@0.0.32
check@1.2.5
coffeescript@1.12.3_1
dandv:caret-position@2.1.1
ddp@1.2.5
ddp-client@1.3.3
ddp-client@1.3.4
ddp-common@1.2.8
ddp-rate-limiter@1.0.6
ddp-server@1.3.13
ddp-rate-limiter@1.0.7
ddp-server@1.3.14
deepwell:bootstrap-datepicker2@1.3.0
deps@1.0.12
diff-sequence@1.0.7
dispatch:run-as-user@1.1.1
ecmascript@0.6.3
ecmascript@0.7.3
ecmascript-runtime@0.3.15
edgee:slingshot@0.7.1
ejson@1.0.13
email@1.1.18
email@1.2.1
emojione:emojione@2.2.6
facebook-oauth@1.3.0
fastclick@1.0.13
francocatena:status@1.5.3
geojson-utils@1.0.10
github-oauth@1.2.0
google-oauth@1.2.0
google-oauth@1.2.4
hot-code-push@1.0.4
html-tools@1.0.11
htmljs@1.0.11
http@1.2.11
http@1.2.12
id-map@1.0.9
jalik:ufs@0.7.4_1
jalik:ufs-gridfs@0.1.4
jalik:ufs-local@0.2.8
jalik:ufs-gridfs@0.2.1
jalik:ufs-local@0.2.9
jparker:crypto-core@0.1.0
jparker:crypto-md5@0.1.1
jparker:gravatar@0.5.1
@ -77,17 +77,18 @@ meteor@1.6.1
meteor-base@1.0.4
meteor-developer-oauth@1.2.0
meteorhacks:inject-initial@1.0.4
meteorhacks:meteorx@1.4.1
meteorspark:util@0.2.0
minifier-css@1.2.16
minifier-js@1.2.18
minimongo@1.0.20
minifier-js@2.0.0
minimongo@1.0.23
mizzao:autocomplete@0.5.1
mizzao:timesync@0.3.4
mobile-experience@1.0.4
mobile-status-bar@1.0.14
modules@0.7.9
modules-runtime@0.7.9
mongo@1.1.15
modules@0.8.2
modules-runtime@0.7.10
mongo@1.1.17
mongo-id@1.0.6
mongo-livedata@1.0.12
mrt:reactive-store@0.0.1
@ -95,11 +96,11 @@ mystor:device-detection@0.2.0
nimble:restivus@0.8.12
nooitaf:colors@1.1.2_1
npm-bcrypt@0.9.2
npm-mongo@2.2.16_1
npm-mongo@2.2.24
oauth@1.1.13
oauth1@1.1.11
oauth2@1.1.11
observe-sequence@1.0.15
observe-sequence@1.0.16
ordered-dict@1.0.9
ostrio:cookies@2.2.0
pauli:accounts-linkedin@2.1.2
@ -114,7 +115,7 @@ raix:handlebar-helpers@0.2.5
raix:push@3.0.3-rc.7
raix:ui-dropped-event@0.0.7
random@1.0.10
rate-limit@1.0.6
rate-limit@1.0.8
reactive-dict@1.1.8
reactive-var@1.0.11
reload@1.1.11
@ -137,6 +138,7 @@ rocketchat:crowd@1.0.0
rocketchat:custom-oauth@1.0.0
rocketchat:custom-sounds@1.0.0
rocketchat:dolphin@0.0.2
rocketchat:drupal@0.0.1
rocketchat:emoji@1.0.0
rocketchat:emoji-custom@1.0.0
rocketchat:emoji-emojione@0.0.1
@ -176,6 +178,7 @@ rocketchat:message-pin@0.0.1
rocketchat:message-snippet@0.0.1
rocketchat:message-star@0.0.1
rocketchat:migrations@0.0.1
rocketchat:monitoring@2.30.2_3
rocketchat:oauth2-server@2.0.0
rocketchat:oauth2-server-config@1.0.0
rocketchat:oembed@0.0.1
@ -223,30 +226,30 @@ routepolicy@1.0.12
service-configuration@1.0.11
session@1.1.7
sha@1.0.9
shell-server@0.2.2
shell-server@0.2.3
simple:json-routes@2.1.0
smoral:sweetalert@1.1.1
spacebars@1.0.13
spacebars-compiler@1.1.0
spacebars@1.0.15
spacebars-compiler@1.1.2
srp@1.0.10
standard-minifier-css@1.3.4
standard-minifier-js@1.2.3
standard-minifier-js@2.0.0
steffo:meteor-accounts-saml@0.0.1
tap:i18n@1.8.2
templating@1.3.0
templating-compiler@1.3.0
templating-runtime@1.3.0
templating-tools@1.1.0
templating@1.3.2
templating-compiler@1.3.2
templating-runtime@1.3.2
templating-tools@1.1.2
tmeasday:crypto-base@3.1.2
tmeasday:crypto-md5@3.1.2
todda00:friendly-slugs@0.6.0
tracker@1.1.2
tracker@1.1.3
twitter-oauth@1.2.0
ui@1.0.12
ui@1.0.13
underscore@1.0.10
underscorestring:underscore.string@3.3.4
url@1.1.0
webapp@1.3.13
webapp@1.3.15
webapp-hashing@1.0.9
yasaricli:slugify@0.0.7
yasinuslu:blaze-meta@0.3.3

@ -21,7 +21,7 @@ const pkgdef :Spk.PackageDefinition = (
appVersion = 62, # Increment this for every release.
appMarketingVersion = (defaultText = "0.55.0-develop"),
appMarketingVersion = (defaultText = "0.56.0-develop"),
# Human-readable representation of appVersion. Should match the way you
# identify versions of your app in documentation and marketing.

@ -0,0 +1,47 @@
/* eslint object-shorthand: 0, prefer-template: 0 */
const path = require('path');
const fs = require('fs');
let pkgJson = {};
try {
pkgJson = require(path.resolve(
process.cwd(),
'./package.json'
));
} catch (err) {
console.error('no root package.json found');
}
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const files = [
'./package.json',
'./.sandstorm/sandstorm-pkgdef.capnp',
'./.travis/snap.sh',
'./packages/rocketchat-lib/rocketchat.info'
];
console.log('Current version:', pkgJson.version);
rl.question('New version: ', function(version) {
rl.close();
version = version.trim();
if (version === '') {
return;
}
console.log('Updating files to version ' + version);
files.forEach(function(file) {
const data = fs.readFileSync(file, 'utf8');
fs.writeFileSync(file, data.replace(pkgJson.version, version), 'utf8');
});
});

@ -0,0 +1,61 @@
![Rocket.Chat logo](https://rocket.chat/images/logo/logo-dark.svg?v3)
# rocketchat-server snap for Ubuntu Core (all arch)
Features:
* bundles ubuntu distribution specific and RC compatible mongodb version
* oplog tailing for mongo by default
* mongodb backup command
* mongodb restore command
* caddy reverse proxy built-in - capable of handling free lestencrypt ssl
Note:
Currently, this repository is mirrored on launchpad, and used to build latest ARMHF and i386 snaps.
You can download recent builds here:
https://code.launchpad.net/~sing-li/+snap/rocketchat-server
Due an issue with the existing installed base of amd64 users (existing snap always installed mongodb 3.2 [#issue](https://github.com/RocketChat/rocketchat-server-snap/issues/3)), this snap is not currently used for amd64 builds.
### Test installation
Download the latest snap file of the corresponding architecture to your Ubuntu Core 16 or 16.04LTS server.
`sudo snap install ./rocketchat-server-xxxxxxxx.snap --dangerous`
### Development or compile your own snap
Make sure you have `snapcraft` installed.
```
git clone https://github.com/RocketChat/rocketchat-server-snap
cd rocketchat-server-snap
snapcraft snap
```
### Regression tests (run for amd64, i386 and armhf):
- snapcraft runs properly
- snap installs properly
- all services start automatically
- rc service shows a 5-second restart delay while waiting for mongo
- to test manually, stop rc, stop mongo, start rc, wait 20s or so, start mongo
- rc can be successfully restarted via the "Restart the server" button under Admin > Settings > General
- rc service shows a 5-second delay when restarted via this button
- all commands execute successfully:
- initcaddy
- modify the Caddyfile to test:
- self-signed TLS certificate (use the "tls self_signed" caddy directive)
- changing ports (with and without TLS)
- using IP address (only works without TLS)
- successfully acquiring a Let's Encrypt certificate (requires a registered domain)
- backupdb
- should run only with sudo
- restoredb
- ideally, stop rc service prior to running this (mongo must be running)
- should run only with sudo
- use any file outside of $snap_common (should fail)
- use the file created with backupdb
- use a dummy .tgz file without actual data
- with and without a "parties" directory in the archive

@ -0,0 +1,102 @@
#
# Easiest way to work with this file, from an updated Ubuntu 16.04 LTS image
# 1. create a non-root user with sudo priv and perform following steps as non-root
# 2. `sudo apt-get update`
# 3. `sudo apt-get install snapcraft python build-essential`
# 4. `snapcraft stage`
# 5. `snapcraft snap`
name: rocketchat-server
version: #{RC_VERSION}
summary: Rocket.Chat server
description: Have your own Slack like online chat, built with Meteor. https://rocket.chat/
confinement: strict
assumes: [snapd2.21]
apps:
rocketchat-server:
command: startRocketChat
daemon: simple
plugs: [network, network-bind]
rocketchat-mongo:
command: startmongo
daemon: simple
plugs: [network, network-bind]
rocketchat-caddy:
command: env LC_ALL=C caddy -conf=$SNAP_DATA/Caddyfile -host=localhost:8080
daemon: simple
plugs: [network, network-bind]
mongo:
command: env LC_ALL=C mongo
plugs: [network]
restoredb:
command: env LC_ALL=C restoredb
plugs: [network]
backupdb:
command: env LC_ALL=c rcbackup
plugs: [network]
initcaddy:
command: env LC_ALL=c initcaddy
parts:
node:
plugin: nodejs
node-engine: 4.8.1
node-packages:
- promise
- fibers
- underscore
- source-map-support
- semver
build-packages:
# For fibers
- python
- build-essential
- nodejs
organize:
lib/node_modules: node_modules
rocketchat-server:
plugin: dump
after: [node]
source: https://rocket.chat/releases/release-candidate/download
source-type: tar
stage-packages:
- graphicsmagick
stage:
- programs
- main.js
- .node_version.txt
- usr
- lib
mongodb:
build-packages:
- wget
source: ./
prepare: ./resources/preparemongo
plugin: dump
stage-packages:
- libssl1.0.0
prime:
- usr
- bin
- lib
scripts:
plugin: dump
source: resources/
organize:
rcbackup: bin/rcbackup
restoredb: bin/restoredb
startmongo: bin/startmongo
startRocketChat: bin/startRocketChat
initreplset.js: bin/initreplset.js
Caddyfile: bin/Caddyfile
initcaddy: bin/initcaddy
prime:
- bin
caddy:
prepare: ./resources/preparecaddy
plugin: dump
source: ./
prime:
- bin
organize:
caddy: bin/caddy
after: [mongodb]

@ -7,23 +7,30 @@
# 5. `snapcraft snap`
name: rocketchat-server
version: 0.55.0-develop
version: #{RC_VERSION}
summary: Rocket.Chat server
description: Have your own Slack like online chat, built with Meteor. https://rocket.chat/
confinement: strict
assumes: [snapd2.21]
apps:
rocketchat-server:
command: env BABEL_CACHE_DIR=/tmp ROOT_URL=http://localhost PORT=3000 MONGO_URL=mongodb://localhost:27017/parties Accounts_AvatarStorePath=$SNAP_COMMON/uploads node $SNAP/main.js
command: startRocketChat
daemon: simple
plugs: [network, network-bind]
rocketchat-mongo:
command: env LC_ALL=C mongod --bind_ip 127.0.0.1 --smallfiles --dbpath=$SNAP_COMMON
command: startmongo
daemon: simple
plugs: [network, network-bind]
rocketchat-caddy:
command: env LC_ALL=C caddy -conf=$SNAP_DATA/Caddyfile -host=localhost:8080
daemon: simple
plugs: [network, network-bind]
mongo:
command: env LC_ALL=C mongo
plugs: [network]
restoredb:
command: env LC_ALL=C restoredb
plugs: [network]
backupdb:
command: env LC_ALL=c rcbackup
plugs: [network]
@ -48,7 +55,7 @@ parts:
lib/node_modules: node_modules
rocketchat-server:
plugin: dump
after: [mongodb]
after: [node]
source: https://rocket.chat/releases/develop/download
source-type: tar
stage-packages:
@ -59,22 +66,15 @@ parts:
- .node_version.txt
- usr
- lib
snap:
- programs
- main.js
- .node_version.txt
- usr
- lib
mongodb:
source: https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-3.2.7.tgz
build-packages:
- wget
source: ./
prepare: ./resources/preparemongo
plugin: dump
stage-packages:
- libssl1.0.0
stage:
- usr
- bin
- lib
snap:
prime:
- usr
- bin
- lib
@ -83,18 +83,20 @@ parts:
source: resources/
organize:
rcbackup: bin/rcbackup
restoredb: bin/restoredb
startmongo: bin/startmongo
initmongo: bin/initmongo
startRocketChat: bin/startRocketChat
initreplset.js: bin/initreplset.js
Caddyfile: bin/Caddyfile
initcaddy: bin/initcaddy
initmongoreplset.js: bin/initmongoreplset.js
snap:
prime:
- bin
caddy:
plugin: go
go-importpath: github.com/mholt/caddy
source: https://github.com/mholt/caddy
source-type: git
source-commit: 53e117802fedd5915eeb32907873d8786a4b2936
snap:
- bin/caddy
prepare: ./resources/preparecaddy
plugin: dump
source: ./
prime:
- bin
organize:
caddy: bin/caddy
after: [mongodb]

@ -1,6 +0,0 @@
#!/bin/sh
echo "initializing replset if necessary... in 60 seconds"
sleep 60
echo "after 60 seconds, checking for replset..."
mongo $SNAP/bin/initmongoreplset.js

@ -1,8 +0,0 @@
var ism = db.isMaster();
printjson(ism);
if (ism.ismaster) {
} else
{
var msg = rs.initiate();
printjson(msg);
}

@ -0,0 +1,13 @@
var ism = db.isMaster();
if (!ism.ismaster) {
rs.initiate(
{
_id: 'rs0',
members: [
{
_id: 0,
host: 'localhost:27017'
}
]
});
}

@ -0,0 +1,36 @@
#! /bin/bash
caddy_bin="caddy"
caddy_dl_ext=".tar.gz"
# NOTE: `uname -m` is more accurate and universal than `arch`
# See https://en.wikipedia.org/wiki/Uname
unamem="$(uname -m)"
if [[ $unamem == *aarch64* ]]; then
caddy_arch="arm64"
elif [[ $unamem == *64* ]]; then
caddy_arch="amd64"
elif [[ $unamem == *86* ]]; then
caddy_arch="386"
elif [[ $unamem == *armv5* ]]; then
caddy_arch="arm"
caddy_arm="5"
elif [[ $unamem == *armv6l* ]]; then
caddy_arch="arm"
caddy_arm="6"
elif [[ $unamem == *armv7l* ]]; then
caddy_arch="arm"
caddy_arm="7"
else
echo "Aborted, unsupported or unknown architecture: $unamem"
return 2
fi
echo "Downloading Caddy for $caddy_os/$caddy_arch$caddy_arm..."
caddy_file="caddy_linux_$caddy_arch${caddy_arm}_custom$caddy_dl_ext"
caddy_url="https://caddyserver.com/download/linux/$caddy_arch$caddy_arm?plugins=$caddy_plugins"
echo "$caddy_url"
wget --quiet "$caddy_url" -O "$caddy_file"
tar -xzf $caddy_file -C . "$caddy_bin"
chmod +x $caddy_bin

@ -0,0 +1,22 @@
#! /bin/bash
if [[ $(uname -m) == "x86_64" ]]
then
wget --backups=0 "https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-3.2.7.tgz"
tar -zxf ./mongodb-linux-x86_64-ubuntu1604-3.2.7.tgz --strip-components=1
else
IFS=" " read -a links <<< $(apt-get -y --print-uris install mongodb | egrep -o "https?://[^']+")
for link in ${links[@]}
do
wget --backups=0 ${link}
done
IFS=" " read -a deb_pkgs <<< $(ls ./ | egrep "\.deb")
for pkg in ${deb_pkgs[@]}
do
echo "Extracting ${pkg}..."
dpkg-deb -R ${pkg} ./
done
mv usr/bin bin
fi

@ -0,0 +1,72 @@
#! /bin/bash
if [[ ${EUID} != 0 ]]
then
echo "[-] This task must be run with 'sudo'."
exit
fi
backup_file=${1}
if [[ ! -f ${backup_file} ]]
then
echo "[-] Usage: snap run rocketchat-server.restoredb ${SNAP_COMMON}/backup_file.tgz"
exit
fi
cd ${backup_file%/*}
if [[ -z $(pwd | grep "${SNAP_COMMON}") ]]
then
echo "[-] Backup file must be within ${SNAP_COMMON}."
exit
fi
function ask_backup {
echo -n "\
*** ATTENTION ***
* Your current database WILL BE DROPPED prior to the restore!
* Would you like to make a backup of the current database before proceeding?
* (y/n/Q)> "
read choice
[[ "${choice,,}" = n* ]] && return
[[ "${choice,,}" = y* ]] && backupdb && return
exit
}
function warn {
echo "[!] ${1}"
echo "[*] Check ${restore_dir}/${log_name} for details."
}
function abort {
echo "[!] ${1}"
echo "[*] Check ${restore_dir}/${log_name} for details."
echo "[-] Restore aborted!"
exit
}
mongo parties --eval "db.getCollectionNames()" | grep "\[ \]" >> /dev/null || ask_backup
echo "[*] Extracting backup file..."
restore_dir="${SNAP_COMMON}/restore"
log_name="extraction.log"
mkdir -p ${restore_dir}
cd ${restore_dir}
tar --no-same-owner --overwrite -zxvf ${backup_file} &> "${restore_dir}/${log_name}"
[[ $? != 0 ]] && abort "Failed to extract backup files to ${restore_dir}!"
echo "[*] Restoring data..."
data_dir=$(tail "${restore_dir}/${log_name}" | grep parties/. | head -n 1)
[[ -z ${data_dir} ]] && abort "Restore data not found within ${backup_file}!
Please check that your backup file contains the backup data within the \"parties\" directory."
data_dir=$(dirname ${data_dir})
log_name="mongorestore.log"
mongorestore --db parties --noIndexRestore --drop ${data_dir} &> "${restore_dir}/${log_name}"
[[ $? != 0 ]] && abort "Failed to execute mongorestore from ${data_dir}!"
# If mongorestore.log only has a few lines, it likely didn't find the dump files
log_lines=$(wc -l < "${restore_dir}/${log_name}")
[[ ${log_lines} -lt 24 ]] && warn "Little or no restore data found within ${backup_file}!
Please check that your backup file contains all the backup data within the \"parties\" directory."
echo "[*] Preparing database..."
log_name="mongoprepare.log"
mongo parties --eval "db.repairDatabase()" --verbose &> "${restore_dir}/${log_name}"
[[ $? != 0 ]] && abort "Failed to prepare database for usage!"
echo "[+] Restore completed! Please restart the snap.rocketchat services to verify."

@ -0,0 +1,43 @@
#!/bin/bash
function start_rocketchat {
echo "Checking if oplog has been enabled, and enabling if not"
LC_ALL=C mongo $SNAP/bin/initreplset.js
export DEPLOY_METHOD=snap
export NODE_ENV=production
export BABEL_CACHE_DIR=/tmp
export ROOT_URL=http://localhost
export PORT=3000
export MONGO_URL=mongodb://localhost:27017/parties
export MONGO_OPLOG_URL=mongodb://localhost:27017/local
export Accounts_AvatarStorePath=$SNAP_COMMON/uploads
node $SNAP/main.js
}
sleep_time=5
try_times=0
function try_start {
search=$(ps --pid $(cat $SNAP_COMMON/mongod.pid) -o comm=)
if [ $search ]
then
start_rocketchat
else
if [[ "$try_times" == 5 || "$try_times" > 5 ]]; then
echo "Was unable to connect to Mongo. Please make sure Mongo has started successfully: sudo systemctl status snap.rocketchat-server.rocketchat-mongo to view logs: sudo journalctl -u snap.rocketchat-server.rocketchat-mongo"
exit 1;
fi
((try_times += 1))
((sleep_time += 5))
echo "Mongo is not available, can't start. Waiting ${sleep_time} seconds and trying again"
sleep $sleep_time
try_start
fi
}
try_start

@ -1,7 +1 @@
#!/bin/sh
echo "initializing replset backgrounded..."
$SNAP/bin/initmongo &
echo "Starting mongodb server in replicaset standalone mode..."
mongod --bind_ip 127.0.0.1 --smallfiles --dbpath=$SNAP_COMMON --journal --replSet rcreplset
env LC_ALL=C mongod --bind_ip 127.0.0.1 --pidfilepath $SNAP_COMMON/mongod.pid --smallfiles --journal --dbpath=$SNAP_COMMON --replSet rs0

@ -7,23 +7,30 @@
# 5. `snapcraft snap`
name: rocketchat-server
version: 0.55.0-develop
version: #{RC_VERSION}
summary: Rocket.Chat server
description: Have your own Slack like online chat, built with Meteor. https://rocket.chat/
confinement: strict
assumes: [snapd2.21]
apps:
rocketchat-server:
command: env BABEL_CACHE_DIR=/tmp ROOT_URL=http://localhost PORT=3000 MONGO_URL=mongodb://localhost:27017/parties Accounts_AvatarStorePath=$SNAP_COMMON/uploads node $SNAP/main.js
command: startRocketChat
daemon: simple
plugs: [network, network-bind]
rocketchat-mongo:
command: env LC_ALL=C mongod --bind_ip 127.0.0.1 --smallfiles --dbpath=$SNAP_COMMON
command: startmongo
daemon: simple
plugs: [network, network-bind]
rocketchat-caddy:
command: env LC_ALL=C caddy -conf=$SNAP_DATA/Caddyfile -host=localhost:8080
daemon: simple
plugs: [network, network-bind]
mongo:
command: env LC_ALL=C mongo
plugs: [network]
restoredb:
command: env LC_ALL=C restoredb
plugs: [network]
backupdb:
command: env LC_ALL=c rcbackup
plugs: [network]
@ -48,7 +55,7 @@ parts:
lib/node_modules: node_modules
rocketchat-server:
plugin: dump
after: [mongodb]
after: [node]
source: https://rocket.chat/releases/latest/download
source-type: tar
stage-packages:
@ -59,22 +66,15 @@ parts:
- .node_version.txt
- usr
- lib
snap:
- programs
- main.js
- .node_version.txt
- usr
- lib
mongodb:
source: https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-3.2.7.tgz
build-packages:
- wget
source: ./
prepare: ./resources/preparemongo
plugin: dump
stage-packages:
- libssl1.0.0
stage:
- usr
- bin
- lib
snap:
prime:
- usr
- bin
- lib
@ -83,18 +83,20 @@ parts:
source: resources/
organize:
rcbackup: bin/rcbackup
restoredb: bin/restoredb
startmongo: bin/startmongo
initmongo: bin/initmongo
startRocketChat: bin/startRocketChat
initreplset.js: bin/initreplset.js
Caddyfile: bin/Caddyfile
initcaddy: bin/initcaddy
initmongoreplset.js: bin/initmongoreplset.js
snap:
prime:
- bin
caddy:
plugin: go
go-importpath: github.com/mholt/caddy
source: https://github.com/mholt/caddy
source-type: git
source-commit: 53e117802fedd5915eeb32907873d8786a4b2936
snap:
- bin/caddy
prepare: ./resources/preparecaddy
plugin: dump
source: ./
prime:
- bin
organize:
caddy: bin/caddy
after: [mongodb]

@ -1,2 +0,0 @@
**/lesshat.less
**/_lesshat.import.less

@ -107,6 +107,5 @@
"value-list-comma-space-after": "always-single-line",
"value-list-comma-space-before": "never",
"value-list-max-empty-lines": 0,
},
"ignoreFiles": "packages/rocketchat-livechat/app/client/stylesheets/utils/_lesshat.import.less"
}
}

@ -5,8 +5,8 @@ services:
branches:
only:
- develop
- experimental
- "/^(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)$/"
- release-candidate
- "/^\\d+\\.\\d+\\.\\d+(-rc\\.\\d+)?$/"
git:
depth: 1
node_js:

@ -9,11 +9,15 @@ git config user.name "CI Bot"
git config user.email "rocketchat.buildmaster@git.launchpad.net"
# Determine the channel to push snap to.
if [[ $TRAVIS_TAG ]]
then
if [[ $TRAVIS_TAG =~ ^[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+ ]]; then
CHANNEL=candidate
RC_VERSION=$TRAVIS_TAG
elif [[ $TRAVIS_TAG ]]; then
CHANNEL=stable
RC_VERSION=$TRAVIS_TAG
else
CHANNEL=edge
RC_VERSION=0.56.0-develop
fi
echo "Preparing to trigger a snap release for $CHANNEL channel"
@ -33,7 +37,9 @@ echo "Tag: $TRAVIS_TAG \r\nBranch: $TRAVIS_BRANCH\r\nBuild: $TRAVIS_BUILD_NUMBER
GIT_SSH_COMMAND="ssh -i launchpadkey" git clone -b $CHANNEL git+ssh://rocket.chat.buildmaster@git.launchpad.net/rocket.chat launchpad
# Rarely will change, but just incase we copy it all
cp -r resources $CHANNEL/snapcraft.yaml buildinfo launchpad/
cp -r resources buildinfo launchpad/
sed s/#{RC_VERSION}/$RC_VERSION/ $CHANNEL/snapcraft.yaml > launchpad/snapcraft.yaml
cd launchpad
git add resources snapcraft.yaml buildinfo

@ -1,14 +1,211 @@
# History
<a name="0.56.0-develop"></a>
# 0.56.0-develop (2017-04-18)
## NEXT
- [NEW] Permission `join-without-join-code` assigned to admins and bots by default (#6139)
- [NEW] Integrations, both incoming and outgoing, now have access to the models. Example: `Users.findOneById(id)` (#6336)
- [NEW] Option to enable `Two Factor Authentication` in user's account preference
- [FIX] Incoming integrations would break when trying to use the `Store` feature.
- [FIX] Outgoing webhooks which have an error and they're retrying would still retry even if the integration was disabled. (#4835)
- [FIX] Removed Deprecated Package rocketchat:sharedsecret.
- [BREAK] `getUsersOfRoom` API to return array of objects with user and username, instead of array of strings
### New Features
- [#6615](https://github.com/RocketChat/Rocket.Chat/pull/6615) Add a setting to not run outgoing integrations on message edits
- [#6692](https://github.com/RocketChat/Rocket.Chat/pull/6692) Use tokenSentVia parameter for clientid/secret to token endpoint
### Bug Fixes
- [#6709](https://github.com/RocketChat/Rocket.Chat/pull/6709) emoji picker exception
- [#6709](https://github.com/RocketChat/Rocket.Chat/pull/6709) emoji picker exception
- [#6704](https://github.com/RocketChat/Rocket.Chat/pull/6704) Fix message types
<details>
<summary>Others</summary>
- [#6703](https://github.com/RocketChat/Rocket.Chat/pull/6703) LingoHub based on develop
- [#6706](https://github.com/RocketChat/Rocket.Chat/pull/6706) meteor update to 1.4.4
</details>
<a name="0.55.0"></a>
# 0.55.0 (2017-04-18)
### Bug Fixes
- [#6709](https://github.com/RocketChat/Rocket.Chat/pull/6709) emoji picker exception
<a name="0.55.0-rc.6"></a>
# 0.55.0-rc.6 (2017-04-17)
### Bug Fixes
- [#6704](https://github.com/RocketChat/Rocket.Chat/pull/6704) Fix message types
<a name="0.55.0-rc.5"></a>
# 0.55.0-rc.5 (2017-04-13)
### Bug Fixes
- [#6684](https://github.com/RocketChat/Rocket.Chat/pull/6684) Allow question on OAuth token path
- [#6683](https://github.com/RocketChat/Rocket.Chat/pull/6683) Error when returning undefined from incoming intergation’s script
- [#6686](https://github.com/RocketChat/Rocket.Chat/pull/6686) Update server cache indexes on record updates
<a name="0.55.0-rc.4"></a>
# 0.55.0-rc.4 (2017-04-13)
### New Features
- [#6681](https://github.com/RocketChat/Rocket.Chat/pull/6681) Expose Livechat to Incoming Integrations and allow response
### Bug Fixes
- [#6659](https://github.com/RocketChat/Rocket.Chat/pull/6659) Administrators being rate limited when editing users data
- [#6680](https://github.com/RocketChat/Rocket.Chat/pull/6680) Downgrade email package to from 1.2.0 to 1.1.18
- [#6682](https://github.com/RocketChat/Rocket.Chat/pull/6682) Fix Logger stdout publication
<a name="0.55.0-rc.3"></a>
# 0.55.0-rc.3 (2017-04-11)
### Bug Fixes
- [#6658](https://github.com/RocketChat/Rocket.Chat/pull/6658) Revert unwanted UI changes
<a name="0.55.0-rc.2"></a>
# 0.55.0-rc.2 (2017-04-10)
### New Features
- [#6634](https://github.com/RocketChat/Rocket.Chat/pull/6634) Add monitoring package
- [#6632](https://github.com/RocketChat/Rocket.Chat/pull/6632) Drupal oAuth Integration for Rocketchat
### Bug Fixes
- [#6648](https://github.com/RocketChat/Rocket.Chat/pull/6648) Do not escaping markdown on message attachments
- [#6651](https://github.com/RocketChat/Rocket.Chat/pull/6651) Encode avatar url to prevent CSS injection
- [#6650](https://github.com/RocketChat/Rocket.Chat/pull/6650) Improve markdown code
<details>
<summary>Others</summary>
- [#6649](https://github.com/RocketChat/Rocket.Chat/pull/6649) Added Deploy method and platform to stats
- [#6647](https://github.com/RocketChat/Rocket.Chat/pull/6647) LingoHub based on develop
- [#6631](https://github.com/RocketChat/Rocket.Chat/pull/6631) meteor update
</details>
<a name="0.55.0-rc.1"></a>
# 0.55.0-rc.1 (2017-04-07)
### New Features
- [#6616](https://github.com/RocketChat/Rocket.Chat/pull/6616) 'users.resetAvatar' rest api endpoint
### Bug Fixes
- [#6617](https://github.com/RocketChat/Rocket.Chat/pull/6617) arguments logger
- [#6620](https://github.com/RocketChat/Rocket.Chat/pull/6620) Incorrect curl command being generated on incoming integrations
<a name="0.55.0-rc.0"></a>
# 0.55.0-rc.0 (2017-04-06)
### BREACKING CHANGES
- :hand: `getUsersOfRoom` API to return array of objects with user and username, instead of array of strings
### New Features
- :hand: Permission `join-without-join-code` assigned to admins and bots by default (#6139)
- :hand: Integrations, both incoming and outgoing, now have access to the models. Example: `Users.findOneById(id)` (#6336)
- [#6565](https://github.com/RocketChat/Rocket.Chat/pull/6565) Add shield.svg api route to generate custom shields/badges
- [#6554](https://github.com/RocketChat/Rocket.Chat/pull/6554) Added oauth2 userinfo endpoint
- [#6577](https://github.com/RocketChat/Rocket.Chat/pull/6577) resolve merge share function
- [#6608](https://github.com/RocketChat/Rocket.Chat/pull/6608) Switch Snaps to use oplog
- [#6476](https://github.com/RocketChat/Rocket.Chat/pull/6476) Two Factor Auth
### Bug Fixes
- :hand: Incoming integrations would break when trying to use the `Store` feature.
- :hand: Outgoing webhooks which have an error and they're retrying would still retry even if the integration was disabled. (#4835)
- :hand: Removed Deprecated Package rocketchat:sharedsecret.
- [#6590](https://github.com/RocketChat/Rocket.Chat/pull/6590) Accounts from LinkedIn OAuth without name
- [#6531](https://github.com/RocketChat/Rocket.Chat/pull/6531) can not get access_token when using custom oauth
- [#6594](https://github.com/RocketChat/Rocket.Chat/pull/6594) Do not add default roles for users without services field
- [#6598](https://github.com/RocketChat/Rocket.Chat/pull/6598) Large files crashed browser when trying to show preview
- [#6600](https://github.com/RocketChat/Rocket.Chat/pull/6600) messageBox: put "joinCodeRequired" back
- [#6575](https://github.com/RocketChat/Rocket.Chat/pull/6575) Usage of subtagged languages
- [#6562](https://github.com/RocketChat/Rocket.Chat/pull/6562) UTC offset missing UTC text when positive
<details>
<summary>Others</summary>
- [#6597](https://github.com/RocketChat/Rocket.Chat/pull/6597) Add `fname` to subscriptions in memory
- [#6614](https://github.com/RocketChat/Rocket.Chat/pull/6614) Add candidate snap channel
- [#6458](https://github.com/RocketChat/Rocket.Chat/pull/6458) Add ESLint rule `one-var`
- [#6280](https://github.com/RocketChat/Rocket.Chat/pull/6280) Clipboard [Firefox version < 50]
- [#6503](https://github.com/RocketChat/Rocket.Chat/pull/6503) Convert File Package to js
- [#6471](https://github.com/RocketChat/Rocket.Chat/pull/6471) convert mapview package to js
- [#6576](https://github.com/RocketChat/Rocket.Chat/pull/6576) Convert Message Pin Package to JS
- [#6539](https://github.com/RocketChat/Rocket.Chat/pull/6539) convert rocketchat-ui part 2
- [#6446](https://github.com/RocketChat/Rocket.Chat/pull/6446) Convert Tutum Package to JS
- [#6561](https://github.com/RocketChat/Rocket.Chat/pull/6561) Convert Ui-Login Package to Js
- [#6498](https://github.com/RocketChat/Rocket.Chat/pull/6498) Convert Ui-Master Package to Js
- [#6473](https://github.com/RocketChat/Rocket.Chat/pull/6473) Convert ui-vrecord Package to JS
- [#6494](https://github.com/RocketChat/Rocket.Chat/pull/6494) Convert Version Package to JS
- [#6499](https://github.com/RocketChat/Rocket.Chat/pull/6499) Convert Wordpress Package to js
- [#6496](https://github.com/RocketChat/Rocket.Chat/pull/6496) converted getAvatarUrlFromUsername
- [#6500](https://github.com/RocketChat/Rocket.Chat/pull/6500) converted messageAttachment coffee to js
- [#6467](https://github.com/RocketChat/Rocket.Chat/pull/6467) converted rocketchat-mentions coffee to js
- [#6497](https://github.com/RocketChat/Rocket.Chat/pull/6497) converted slashcommand-invite coffee to js
- [#6469](https://github.com/RocketChat/Rocket.Chat/pull/6469) converted slashcommand-join coffee to js
- [#6470](https://github.com/RocketChat/Rocket.Chat/pull/6470) converted slashcommand-leave coffee to js
- [#6468](https://github.com/RocketChat/Rocket.Chat/pull/6468) converted slashcommand-me coffee to js
- [#6501](https://github.com/RocketChat/Rocket.Chat/pull/6501) converted slashcommand-msg coffee to js
- [#6474](https://github.com/RocketChat/Rocket.Chat/pull/6474) converted slashcommands-mute coffee to js
- [#6505](https://github.com/RocketChat/Rocket.Chat/pull/6505) Create groups.addAll endpoint and add activeUsersOnly param.
- [#6584](https://github.com/RocketChat/Rocket.Chat/pull/6584) dependencies upgrade
- [#6479](https://github.com/RocketChat/Rocket.Chat/pull/6479) ESLint add rule `no-void`
- [#6591](https://github.com/RocketChat/Rocket.Chat/pull/6591) Fix recently introduced bug: OnePassword not defined
- [#6574](https://github.com/RocketChat/Rocket.Chat/pull/6574) LingoHub based on develop
- [#6567](https://github.com/RocketChat/Rocket.Chat/pull/6567) LingoHub based on develop
- [#6585](https://github.com/RocketChat/Rocket.Chat/pull/6585) Move room display name logic to roomType definition
- [#6571](https://github.com/RocketChat/Rocket.Chat/pull/6571) Move wordpress packages client files to client folder
- [#6351](https://github.com/RocketChat/Rocket.Chat/pull/6351) New feature: Room announcement
- [#6596](https://github.com/RocketChat/Rocket.Chat/pull/6596) Only configure LoggerManager on server
- [#6298](https://github.com/RocketChat/Rocket.Chat/pull/6298) POC Google Natural Language integration
- [#6543](https://github.com/RocketChat/Rocket.Chat/pull/6543) Remove coffeescript package from ui-flextab
- [#6542](https://github.com/RocketChat/Rocket.Chat/pull/6542) Remove coffeescript package from ui-sidenav
- [#6540](https://github.com/RocketChat/Rocket.Chat/pull/6540) Remove Deprecated Shared Secret Package
- [#6551](https://github.com/RocketChat/Rocket.Chat/pull/6551) rocketchat-channel-settings coffee to js
- [#6541](https://github.com/RocketChat/Rocket.Chat/pull/6541) rocketchat-channel-settings-mail-messages coffee to js
- [#6553](https://github.com/RocketChat/Rocket.Chat/pull/6553) rocketchat-lib part1
- [#6504](https://github.com/RocketChat/Rocket.Chat/pull/6504) rocketchat-ui coffee to js part1
- [#3851](https://github.com/RocketChat/Rocket.Chat/pull/3851) Use real name instead of username for messages and direct messages list
</details>
## 0.54.2 - 2017-Mar-24

@ -417,11 +417,15 @@ Thanks to our core team
[Sing Li](https://github.com/Sing-Li),
and to hundreds of awesome [contributors](https://github.com/RocketChat/Rocket.Chat/graphs/contributors).
![Emoji One](https://cloud.githubusercontent.com/assets/1986378/24772858/47290a70-1ae9-11e7-9a5a-2913d0002c94.png)
Emoji provided free by [Emoji One](http://emojione.com)
Performance monitoring provided by [Kadira](https://kadira.io)
![BrowserStack](https://cloud.githubusercontent.com/assets/1986378/24772879/57d57b88-1ae9-11e7-98b4-4af824b47933.png)
Testing with [BrowserStack](https://www.browserstack.com)
Hosting powered by [Rackspace](https://rackspace.com)
# Donate

@ -6,11 +6,13 @@
"keywords": ["meteor", "social", "community", "chat"],
"website": "https://rocket.chat",
"env": {
"NODE_ENV": "production",
"BUILDPACK_URL": "https://github.com/RocketChat/meteor-buildpack-horse.git",
"HEROKU_APP_NAME": {
"description": "Please re-enter your App Name from the top.",
"required": true
}
},
"DEPLOY_PLATFORM": "heroku"
},
"addons": [
"mongolab",

@ -0,0 +1,22 @@
Meteor.startup(function() {
RocketChat.Notifications.onLogged('Users:NameChanged', function({_id, name, username}) {
RocketChat.models.Messages.update({
'u._id': _id
}, {
$set: {
'u.name': name
}
}, {
multi: true
});
RocketChat.models.Subscriptions.update({
name: username,
t: 'd'
}, {
$set: {
fname: name
}
});
});
});

@ -27,7 +27,7 @@ FlowRouter.route('/', {
Tracker.autorun(function(c) {
if (FlowRouter.subsReady() === true) {
Meteor.defer(function() {
if (Meteor.user().defaultRoom) {
if (Meteor.user() && Meteor.user().defaultRoom) {
const room = Meteor.user().defaultRoom.split('/');
FlowRouter.go(room[0], { name: room[1] }, FlowRouter.current().queryParams);
} else {

@ -5,7 +5,7 @@ Meteor.startup(function() {
let unreadCount = 0;
let unreadAlert = false;
const subscriptions = ChatSubscription.find({open: true}, { fields: { unread: 1, alert: 1, rid: 1, t: 1, name: 1, ls: 1, unreadAlert: 1 } });
const subscriptions = ChatSubscription.find({open: true, hideUnreadStatus: { $ne: true }}, { fields: { unread: 1, alert: 1, rid: 1, t: 1, name: 1, ls: 1, unreadAlert: 1 } });
let openedRoomId = undefined;
Tracker.nonreactive(function() {

@ -12,8 +12,8 @@ services:
- MONGO_URL=mongodb://mongo:27017/rocketchat
- MONGO_OPLOG_URL=mongodb://mongo:27017/local
- MAIL_URL=smtp://smtp.email
- HTTP_PROXY=http://proxy.domain.com
- HTTPS_PROXY=http://proxy.domain.com
# - HTTP_PROXY=http://proxy.domain.com
# - HTTPS_PROXY=http://proxy.domain.com
depends_on:
- mongo
ports:

@ -1,7 +1,7 @@
{
"name": "Rocket.Chat",
"description": "The Ultimate Open Source WebChat Platform",
"version": "0.55.0-develop",
"version": "0.56.0-develop",
"author": {
"name": "Rocket.Chat",
"url": "https://rocket.chat/"
@ -42,7 +42,9 @@
"deploy": "npm run build && pm2 startOrRestart pm2.json",
"chimp-watch": "chimp --ddp=http://localhost:3000 --watch --mocha --path=tests/end-to-end",
"chimp-test": "chimp tests/chimp-config.js",
"postinstall": "cd packages/rocketchat-katex && npm i"
"postinstall": "cd packages/rocketchat-katex && npm i",
"version": "node .scripts/version.js",
"release": "npm run version && conventional-changelog --config .github/changelog.js -i HISTORY.md -s"
},
"license": "MIT",
"repository": {
@ -54,24 +56,25 @@
"email": "support@rocket.chat"
},
"devDependencies": {
"chimp": "^0.47.2",
"chimp": "^0.48.0",
"eslint": "^3.19.0",
"stylelint": "^7.10.1",
"supertest": "^3.0.0"
"supertest": "^3.0.0",
"conventional-changelog": "^1.1.3"
},
"dependencies": {
"babel-runtime": "^6.23.0",
"bcrypt": "^1.0.2",
"codemirror": "^5.25.0",
"file-type": "^4.1.0",
"highlight.js": "^9.10.0",
"codemirror": "^5.25.2",
"file-type": "^4.2.0",
"highlight.js": "^9.11.0",
"jquery": "^3.2.1",
"mime-db": "^1.27.0",
"mime-type": "^3.0.4",
"moment": "^2.18.1",
"moment-timezone": "^0.5.12",
"photoswipe": "^4.1.1",
"prom-client": "^8.0.0",
"moment-timezone": "^0.5.13",
"photoswipe": "^4.1.2",
"prom-client": "^8.1.1",
"semver": "^5.3.0",
"toastr": "^2.1.2"
}

@ -19,6 +19,7 @@ Package.onUse(function(api) {
//Register v1 helpers
api.addFiles('server/v1/helpers/getPaginationItems.js', 'server');
api.addFiles('server/v1/helpers/getUserFromParams.js', 'server');
api.addFiles('server/v1/helpers/isUserFromParams.js', 'server');
api.addFiles('server/v1/helpers/parseJsonQuery.js', 'server');
api.addFiles('server/v1/helpers/getLoggedInUser.js', 'server');

@ -1,10 +1,15 @@
//Returns the channel IF found otherwise it will return the failure of why it didn't. Check the `statusCode` property
function findChannelById({ roomId, checkedArchived = true }) {
if (!roomId || !roomId.trim()) {
throw new Meteor.Error('error-roomid-param-not-provided', 'The parameter "roomId" is required');
function findChannelByIdOrName({ roomId, roomName, checkedArchived = true }) {
if ((!roomId || !roomId.trim()) && (!roomName || !roomName.trim())) {
throw new Meteor.Error('error-roomid-param-not-provided', 'The parameter "roomId" or "roomName" is required');
}
const room = RocketChat.models.Rooms.findOneById(roomId, { fields: RocketChat.API.v1.defaultFieldsToExclude });
let room;
if (roomId) {
room = RocketChat.models.Rooms.findOneById(roomId, { fields: RocketChat.API.v1.defaultFieldsToExclude });
} else if (roomName) {
room = RocketChat.models.Rooms.findOneByName(roomName, { fields: RocketChat.API.v1.defaultFieldsToExclude });
}
if (!room || room.t !== 'c') {
throw new Meteor.Error('error-room-not-found', `No channel found by the id of: ${ roomId }`);
@ -19,7 +24,7 @@ function findChannelById({ roomId, checkedArchived = true }) {
RocketChat.API.v1.addRoute('channels.addAll', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
Meteor.runAsUser(this.userId, () => {
Meteor.call('addAllUserToRoom', findResult._id, this.bodyParams.activeUsersOnly);
@ -33,7 +38,7 @@ RocketChat.API.v1.addRoute('channels.addAll', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.addModerator', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
const user = this.getUserFromParams();
@ -47,7 +52,7 @@ RocketChat.API.v1.addRoute('channels.addModerator', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.addOwner', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
const user = this.getUserFromParams();
@ -61,7 +66,7 @@ RocketChat.API.v1.addRoute('channels.addOwner', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.archive', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
Meteor.runAsUser(this.userId, () => {
Meteor.call('archiveRoom', findResult._id);
@ -73,7 +78,7 @@ RocketChat.API.v1.addRoute('channels.archive', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.cleanHistory', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
if (!this.bodyParams.latest) {
return RocketChat.API.v1.failure('Body parameter "latest" is required.');
@ -101,7 +106,7 @@ RocketChat.API.v1.addRoute('channels.cleanHistory', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.close', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId, checkedArchived: false });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId, checkedArchived: false });
const sub = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(findResult._id, this.userId);
@ -157,7 +162,7 @@ RocketChat.API.v1.addRoute('channels.create', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.delete', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId, checkedArchived: false });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId, checkedArchived: false });
//The find method returns either with the group or the failur
@ -177,7 +182,7 @@ RocketChat.API.v1.addRoute('channels.getIntegrations', { authRequired: true }, {
return RocketChat.API.v1.unauthorized();
}
const findResult = findChannelById({ roomId: this.queryParams.roomId, checkedArchived: false });
const findResult = findChannelByIdOrName({ roomId: this.queryParams.roomId, checkedArchived: false });
let includeAllPublicChannels = true;
if (typeof this.queryParams.includeAllPublicChannels !== 'undefined') {
@ -217,7 +222,7 @@ RocketChat.API.v1.addRoute('channels.getIntegrations', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.history', { authRequired: true }, {
get() {
const findResult = findChannelById({ roomId: this.queryParams.roomId, checkedArchived: false });
const findResult = findChannelByIdOrName({ roomId: this.queryParams.roomId, checkedArchived: false });
let latestDate = new Date();
if (this.queryParams.latest) {
@ -257,7 +262,7 @@ RocketChat.API.v1.addRoute('channels.history', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.info', { authRequired: true }, {
get() {
const findResult = findChannelById({ roomId: this.queryParams.roomId, checkedArchived: false });
const findResult = findChannelByIdOrName({ roomId: this.queryParams.roomId, roomName: this.queryParams.roomName, checkedArchived: false });
return RocketChat.API.v1.success({
channel: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
@ -267,7 +272,7 @@ RocketChat.API.v1.addRoute('channels.info', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.invite', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
const user = this.getUserFromParams();
@ -283,7 +288,7 @@ RocketChat.API.v1.addRoute('channels.invite', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.join', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
Meteor.runAsUser(this.userId, () => {
Meteor.call('joinRoom', findResult._id, this.bodyParams.joinCode);
@ -297,7 +302,7 @@ RocketChat.API.v1.addRoute('channels.join', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.kick', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
const user = this.getUserFromParams();
@ -313,7 +318,7 @@ RocketChat.API.v1.addRoute('channels.kick', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.leave', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
Meteor.runAsUser(this.userId, () => {
Meteor.call('leaveRoom', findResult._id);
@ -409,7 +414,7 @@ RocketChat.API.v1.addRoute('channels.online', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.open', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId, checkedArchived: false });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId, checkedArchived: false });
const sub = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(findResult._id, this.userId);
@ -431,7 +436,7 @@ RocketChat.API.v1.addRoute('channels.open', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.removeModerator', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
const user = this.getUserFromParams();
@ -445,7 +450,7 @@ RocketChat.API.v1.addRoute('channels.removeModerator', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.removeOwner', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
const user = this.getUserFromParams();
@ -463,7 +468,7 @@ RocketChat.API.v1.addRoute('channels.rename', { authRequired: true }, {
return RocketChat.API.v1.failure('The bodyParam "name" is required');
}
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
if (findResult.name === this.bodyParams.name) {
return RocketChat.API.v1.failure('The channel name is the same as what it would be renamed to.');
@ -485,7 +490,7 @@ RocketChat.API.v1.addRoute('channels.setDescription', { authRequired: true }, {
return RocketChat.API.v1.failure('The bodyParam "description" is required');
}
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
if (findResult.description === this.bodyParams.description) {
return RocketChat.API.v1.failure('The channel description is the same as what it would be changed to.');
@ -507,7 +512,7 @@ RocketChat.API.v1.addRoute('channels.setJoinCode', { authRequired: true }, {
return RocketChat.API.v1.failure('The bodyParam "joinCode" is required');
}
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
Meteor.runAsUser(this.userId, () => {
Meteor.call('saveRoomSettings', findResult._id, 'joinCode', this.bodyParams.joinCode);
@ -525,7 +530,7 @@ RocketChat.API.v1.addRoute('channels.setPurpose', { authRequired: true }, {
return RocketChat.API.v1.failure('The bodyParam "purpose" is required');
}
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
if (findResult.description === this.bodyParams.purpose) {
return RocketChat.API.v1.failure('The channel purpose (description) is the same as what it would be changed to.');
@ -547,7 +552,7 @@ RocketChat.API.v1.addRoute('channels.setReadOnly', { authRequired: true }, {
return RocketChat.API.v1.failure('The bodyParam "readOnly" is required');
}
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
if (findResult.ro === this.bodyParams.readOnly) {
return RocketChat.API.v1.failure('The channel read only setting is the same as what it would be changed to.');
@ -569,7 +574,7 @@ RocketChat.API.v1.addRoute('channels.setTopic', { authRequired: true }, {
return RocketChat.API.v1.failure('The bodyParam "topic" is required');
}
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
if (findResult.topic === this.bodyParams.topic) {
return RocketChat.API.v1.failure('The channel topic is the same as what it would be changed to.');
@ -591,7 +596,7 @@ RocketChat.API.v1.addRoute('channels.setType', { authRequired: true }, {
return RocketChat.API.v1.failure('The bodyParam "type" is required');
}
const findResult = findChannelById({ roomId: this.bodyParams.roomId });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId });
if (findResult.t === this.bodyParams.type) {
return RocketChat.API.v1.failure('The channel type is the same as what it would be changed to.');
@ -609,7 +614,7 @@ RocketChat.API.v1.addRoute('channels.setType', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.unarchive', { authRequired: true }, {
post() {
const findResult = findChannelById({ roomId: this.bodyParams.roomId, checkedArchived: false });
const findResult = findChannelByIdOrName({ roomId: this.bodyParams.roomId, checkedArchived: false });
if (!findResult.archived) {
return RocketChat.API.v1.failure(`The channel, ${ findResult.name }, is not archived`);

@ -1,4 +1,4 @@
//Returns the private group subscription IF found otherwise it will reutrn the failure of why it didn't. Check the `statusCode` property
//Returns the private group subscription IF found otherwise it will return the failure of why it didn't. Check the `statusCode` property
function findPrivateGroupByIdOrName({ roomId, roomName, userId, checkedArchived = true }) {
if ((!roomId || !roomId.trim()) && (!roomName || !roomName.trim())) {
throw new Meteor.Error('error-roomid-param-not-provided', 'The parameter "roomId" or "roomName" is required');

@ -1,4 +1,4 @@
//Convience method, almost need to turn it into a middleware of sorts
//Convenience method, almost need to turn it into a middleware of sorts
RocketChat.API.v1.helperMethods.set('getUserFromParams', function _getUserFromParams() {
const doesntExist = { _doesntExist: true };
let user;

@ -0,0 +1,5 @@
RocketChat.API.v1.helperMethods.set('isUserFromParams', function _isUserFromParams() {
return (this.queryParams.userId && this.userId === this.queryParams.userId) ||
(this.queryParams.username && this.user.username === this.queryParams.username) ||
(this.queryParams.user && this.user.username === this.queryParams.user);
});

@ -5,9 +5,9 @@ RocketChat.API.v1.addRoute('integrations.create', { authRequired: true }, {
name: String,
enabled: Boolean,
username: String,
urls: [String],
urls: Match.Maybe([String]),
channel: String,
event: String,
event: Match.Maybe(String),
triggerWords: Match.Maybe([String]),
alias: Match.Maybe(String),
avatar: Match.Maybe(String),
@ -26,6 +26,11 @@ RocketChat.API.v1.addRoute('integrations.create', { authRequired: true }, {
integration = Meteor.call('addOutgoingIntegration', this.bodyParams);
});
break;
case 'webhook-incoming':
Meteor.runAsUser(this.userId, () => {
integration = Meteor.call('addIncomingIntegration', this.bodyParams);
});
break;
default:
return RocketChat.API.v1.failure('Invalid integration type.');
}
@ -121,6 +126,20 @@ RocketChat.API.v1.addRoute('integrations.remove', { authRequired: true }, {
Meteor.call('deleteOutgoingIntegration', integration._id);
});
return RocketChat.API.v1.success({
integration
});
case 'webhook-incoming':
integration = RocketChat.models.Integrations.findOne({ _id: this.bodyParams.integrationId });
if (!integration) {
return RocketChat.API.v1.failure('No integration found.');
}
Meteor.runAsUser(this.userId, () => {
Meteor.call('deleteIncomingIntegration', integration._id);
});
return RocketChat.API.v1.success({
integration
});

@ -67,20 +67,19 @@ RocketChat.API.v1.addRoute('users.getAvatar', { authRequired: false }, {
RocketChat.API.v1.addRoute('users.getPresence', { authRequired: true }, {
get() {
//BLAHHHHHHHHHH :'(
if ((this.queryParams.userId && this.userId !== this.queryParams.userId) || (this.queryParams.username && this.user.username !== this.queryParams.username) || (this.queryParams.user && this.user.username !== this.queryParams.user)) {
const user = this.getUserFromParams();
if (this.isUserFromParams()) {
const user = RocketChat.models.Users.findOneById(this.userId);
return RocketChat.API.v1.success({
presence: user.status
presence: user.status,
connectionStatus: user.statusConnection,
lastLogin: user.lastLogin
});
}
const user = RocketChat.models.Users.findOneById(this.userId);
const user = this.getUserFromParams();
return RocketChat.API.v1.success({
presence: user.status,
connectionStatus: user.statusConnection,
lastLogin: user.lastLogin
presence: user.status
});
}
});
@ -169,17 +168,35 @@ RocketChat.API.v1.addRoute('users.register', { authRequired: false }, {
}
});
//TODO: Make this route work with support for usernames
RocketChat.API.v1.addRoute('users.resetAvatar', { authRequired: true }, {
post() {
const user = this.getUserFromParams();
if (user._id === this.userId) {
Meteor.runAsUser(this.userId, () => Meteor.call('resetAvatar'));
} else if (RocketChat.authz.hasPermission(this.userId, 'edit-other-user-info')) {
Meteor.runAsUser(user._id, () => Meteor.call('resetAvatar'));
} else {
return RocketChat.API.v1.unauthorized();
}
return RocketChat.API.v1.success();
}
});
RocketChat.API.v1.addRoute('users.setAvatar', { authRequired: true }, {
post() {
check(this.bodyParams, { avatarUrl: Match.Maybe(String), userId: Match.Maybe(String) });
if (typeof this.bodyParams.userId !== 'undefined' && this.userId !== this.bodyParams.userId && !RocketChat.authz.hasPermission(this.userId, 'edit-other-user-info')) {
let user;
if (this.isUserFromParams()) {
user = Meteor.users.findOne(this.userId);
} else if (RocketChat.authz.hasPermission(this.userId, 'edit-other-user-info')) {
user = this.getUserFromParams();
} else {
return RocketChat.API.v1.unauthorized();
}
const user = Meteor.users.findOne(this.bodyParams.userId ? this.bodyParams.userId : this.userId);
if (this.bodyParams.avatarUrl) {
RocketChat.setUserAvatar(user, this.bodyParams.avatarUrl, '', 'url');
} else {
@ -232,7 +249,7 @@ RocketChat.API.v1.addRoute('users.update', { authRequired: true }, {
const userData = _.extend({ _id: this.bodyParams.userId }, this.bodyParams.data);
RocketChat.saveUser(this.userId, userData);
Meteor.runAsUser(this.userId, () => RocketChat.saveUser(this.userId, userData));
if (this.bodyParams.data.customFields) {
RocketChat.saveCustomFields(this.bodyParams.userId, this.bodyParams.data.customFields);
@ -247,3 +264,14 @@ RocketChat.API.v1.addRoute('users.update', { authRequired: true }, {
return RocketChat.API.v1.success({ user: RocketChat.models.Users.findOneById(this.bodyParams.userId, { fields: RocketChat.API.v1.defaultFieldsToExclude }) });
}
});
RocketChat.API.v1.addRoute('users.createToken', { authRequired: true }, {
post() {
const user = this.getUserFromParams();
let data;
Meteor.runAsUser(this.userId, () => {
data = Meteor.call('createToken', user._id);
});
return data ? RocketChat.API.v1.success({data}) : RocketChat.API.v1.unauthorized();
}
});

@ -1,6 +1,8 @@
RocketChat.authz.cachedCollection = new RocketChat.CachedCollection({
name: 'permissions',
eventType: 'onLogged'
eventType: 'onLogged',
userRelated: false
});
RocketChat.authz.cachedCollection.init();
this.ChatPermissions = RocketChat.authz.cachedCollection.collection;

@ -1,15 +1,19 @@
/* globals RocketChat */
RocketChat.authz.roomAccessValidators = [
function(room, user) {
function(room, user = {}) {
if (room.t === 'c') {
if (!user._id && RocketChat.settings.get('Accounts_AllowAnonymousRead') === true) {
return true;
}
return RocketChat.authz.hasPermission(user._id, 'view-c-room');
}
},
function(room, user = {}) {
const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id);
if (subscription) {
return subscription._room;
}
},
function(room, user) {
if (room.t === 'c') {
return RocketChat.authz.hasPermission(user._id, 'view-c-room');
}
}
];

@ -15,7 +15,7 @@ Meteor.methods({
if (roleName === 'admin' && !RocketChat.authz.hasPermission(Meteor.userId(), 'assign-admin-role')) {
throw new Meteor.Error('error-action-not-allowed', 'Assigning admin is not allowed', {
method: 'insertOrUpdateUser',
method: 'authorization:addUserToRole',
action: 'Assign_admin'
});
}

@ -46,20 +46,21 @@ Meteor.startup(function() {
{ _id: 'set-moderator', roles : ['admin', 'owner'] },
{ _id: 'set-owner', roles : ['admin', 'owner'] },
{ _id: 'unarchive-room', roles : ['admin'] },
{ _id: 'view-c-room', roles : ['admin', 'user', 'bot'] },
{ _id: 'view-c-room', roles : ['admin', 'user', 'bot', 'anonymous'] },
{ _id: 'user-generate-access-token', roles : ['admin'] },
{ _id: 'view-d-room', roles : ['admin', 'user', 'bot'] },
{ _id: 'view-full-other-user-info', roles : ['admin'] },
{ _id: 'view-history', roles : ['admin', 'user'] },
{ _id: 'view-joined-room', roles : ['guest', 'bot'] },
{ _id: 'view-history', roles : ['admin', 'user', 'anonymous'] },
{ _id: 'view-joined-room', roles : ['guest', 'bot', 'anonymous'] },
{ _id: 'view-join-code', roles : ['admin'] },
{ _id: 'view-logs', roles : ['admin'] },
{ _id: 'view-other-user-channels', roles : ['admin'] },
{ _id: 'view-p-room', roles : ['admin', 'user'] },
{ _id: 'view-p-room', roles : ['admin', 'user', 'anonymous'] },
{ _id: 'view-privileged-setting', roles : ['admin'] },
{ _id: 'view-room-administration', roles : ['admin'] },
{ _id: 'view-statistics', roles : ['admin'] },
{ _id: 'view-user-administration', roles : ['admin'] },
{ _id: 'preview-c-room', roles : ['admin', 'user'] }
{ _id: 'preview-c-room', roles : ['admin', 'user', 'anonymous'] }
];
for (const permission of permissions) {
@ -74,7 +75,8 @@ Meteor.startup(function() {
{ name: 'owner', scope: 'Subscriptions', description: 'Owner' },
{ name: 'user', scope: 'Users', description: '' },
{ name: 'bot', scope: 'Users', description: '' },
{ name: 'guest', scope: 'Users', description: '' }
{ name: 'guest', scope: 'Users', description: '' },
{ name: 'anonymous', scope: 'Users', description: '' }
];
for (const role of defaultRoles) {

@ -25,7 +25,7 @@ RocketChat.ChannelSettings = new class {
const allOptions = _.toArray(this.options.get());
const allowedOptions = _.compact(_.map(allOptions, function(option) {
if (option.validation == null || option.validation()) {
option.data = Object.assign({}, option.data, currentData);
option.data = Object.assign({}, typeof option.data === 'function' ? option.data() : option.data, currentData);
return option;
}
})).filter(function(option) {

@ -1,16 +1,49 @@
function data(message) {
return {
user_by: message.u && message.u.username,
room_type: message.msg
};
}
Meteor.startup(function() {
['room_changed_privacy', 'room_changed_topic', 'room_changed_announcement', 'room_changed_description'].forEach(id => {
RocketChat.MessageTypes.registerType({
id,
system: true,
message: id,
data
});
RocketChat.MessageTypes.registerType({
id: 'room_changed_privacy',
system: true,
message: 'room_changed_privacy',
data(message) {
return {
user_by: message.u && message.u.username,
room_type: message.msg
};
}
});
RocketChat.MessageTypes.registerType({
id: 'room_changed_topic',
system: true,
message: 'room_changed_topic',
data(message) {
return {
user_by: message.u && message.u.username,
room_topic: message.msg
};
}
});
RocketChat.MessageTypes.registerType({
id: 'room_changed_announcement',
system: true,
message: 'room_changed_announcement',
data(message) {
return {
user_by: message.u && message.u.username,
room_announcement: message.msg
};
}
});
RocketChat.MessageTypes.registerType({
id: 'room_changed_description',
system: true,
message: 'room_changed_description',
data(message) {
return {
user_by: message.u && message.u.username,
room_description: message.msg
};
}
});
});

@ -2,6 +2,7 @@ Meteor.startup(() => {
RocketChat.TabBar.addButton({
groups: ['channel', 'group', 'direct'],
id: 'channel-settings',
anonymous: true,
i18nTitle: 'Room_Info',
icon: 'icon-info-circled',
template: 'channelSettings',

@ -78,8 +78,10 @@ export class CustomOAuth {
const credentialToken = Random.secret();
const loginStyle = OAuth._loginStyle(this.name, config, options);
const separator = this.authorizePath.indexOf('?') !== -1 ? '&' : '?';
const loginUrl = `${ this.authorizePath
}?client_id=${ config.clientId
}${ separator }client_id=${ config.clientId
}&redirect_uri=${ OAuth._redirectUri(this.name, config)
}&response_type=code` +
`&state=${ OAuth._stateParam(loginStyle, credentialToken, options.redirectUrl)

@ -77,22 +77,30 @@ export class CustomOAuth {
}
let response = undefined;
const allOptions = {
headers: {
'User-Agent': this.userAgent, // http://doc.gitlab.com/ce/api/users.html#Current-user
Accept: 'application/json'
},
params: {
code: query.code,
redirect_uri: OAuth._redirectUri(this.name, config),
grant_type: 'authorization_code',
state: query.state
}
};
// Only send clientID / secret once on header or payload.
if (this.tokenSentVia === 'header') {
allOptions['auth'] = `${ config.clientId }:${ OAuth.openSecret(config.secret) }`;
} else {
allOptions['params']['client_secret'] = OAuth.openSecret(config.secret);
allOptions['params']['client_id'] = config.clientId;
}
try {
response = HTTP.post(this.tokenPath, {
auth: `${ config.clientId }:${ OAuth.openSecret(config.secret) }`,
headers: {
Accept: 'application/json',
'User-Agent': this.userAgent
},
params: {
code: query.code,
client_id: config.clientId,
client_secret: OAuth.openSecret(config.secret),
redirect_uri: OAuth._redirectUri(this.name, config),
grant_type: 'authorization_code',
state: query.state
}
});
response = HTTP.post(this.tokenPath, allOptions);
} catch (err) {
const error = new Error(`Failed to complete OAuth handshake with ${ this.name } at ${ this.tokenPath }. ${ err.message }`);
throw _.extend(error, {response: err.response});

@ -0,0 +1,23 @@
#Drupal oAuth Integration module.
This module works in conjunction with the [Rocket.Chat+ Module for Drupal](https://www.drupal.org/project/rocket_chat)
Version 7.x-1.1 or later.
A full set of instructions for how to connect the 2 are present in the drupal module's documentation.
Basically to connect the 2 you first setup the oAuth server connection in your drupal, with the proper permissions
("Use OAuth2 Server" => "Anonymous User" = Checked).
In the Rocket chat you have to do the following:
- fill in the 'Client ID'.
Bear in mind that the Client ID should not be guessable,but is seen in the URL when doing the login.
- fill in the 'Client Secret'.
This should be treated as a Secret Key (like the Secret Key of a TLS certificate). it __must not__ be guesable or
derivable, and is best a Alphanumerical sequence between 16 and 48 cahracters long (longer would be better but longer
than 48 characters can be problem with long URI's)
- fill in the Drupal's BaseURL.
- on the Drupal use the "Restrict redirect URIs" Setting to limit possible exploits. and set the Redirect URI's to
whatever is in the Callback URL (like `https://Rocketchat.example.com/_oauth/drupal` and possibly also the
`https://Rocketchat.example.com/_oauth/drupal?close` URI.).
- Lastly do not forget to Enable the Drupal OAuth and `SAVE CHANGES`.
When all is a Blue Button with a drupal like logo will apear on the login page of Rocket.Chat+

@ -0,0 +1,39 @@
/* global CustomOAuth */
// Drupal Server CallBack URL needs to be http(s)://{rocketchat.server}[:port]/_oauth/drupal
// In RocketChat -> Administration the URL needs to be http(s)://{drupal.server}/
const config = {
serverURL: '',
identityPath: '/oauth2/UserInfo',
authorizePath: '/oauth2/authorize',
tokenPath: '/oauth2/token',
scope: 'openid email profile offline_access',
tokenSentVia: 'payload',
usernameField: 'preferred_username',
mergeUsers: true,
addAutopublishFields: {
forLoggedInUser: ['services.drupal'],
forOtherUsers: ['services.drupal.name']
}
};
const Drupal = new CustomOAuth('drupal', config);
if (Meteor.isServer) {
Meteor.startup(function() {
RocketChat.settings.get('API_Drupal_URL', function(key, value) {
config.serverURL = value;
Drupal.configure(config);
});
});
} else {
Meteor.startup(function() {
Tracker.autorun(function() {
if (RocketChat.settings.get('API_Drupal_URL')) {
config.serverURL = RocketChat.settings.get('API_Drupal_URL');
Drupal.configure(config);
}
});
});
}

@ -0,0 +1,11 @@
.icon-drupal.service-icon {
display: inline-block;
width: 21px;
height: 28px;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAcCAYAAACOGPReAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAcNJREFUSMetlbFrFFEQh7/dJnhpDHcx6SyiRLhLkUKDsRZB8S9IWi2Syj8iVooQ0FLBNlqJRpNO8Br7FLkoRDBooQHhNCr6WTjB48zd7d7uNI+d+c333pt9bx5kNPVGVm1WYF39rTbKhD7zr62XBVwI4MsYF4sCZ9S2uq6mMbbVmWGBx9WW+kGdCN+J+G6pY3mBo2pT/ape6IrNx2qb6mhW4Ii6qf5Ur/TQXI74pjoyCJioa3F8FgdoF0K3pib9hLfiDy9l3NVS6G/3EiyH4GbO+q9E3nJ3oKF+Vx/33Urvkj2K/EZn4JW6l/uY/MsfU9+rzUPHXCz/+jDADvC14Myhrqpf1EpB6LHgrCbqa+BzkiSXikAD/ByopcAUsFUUGLYFTKVABWiXBG0DlRTYB8ZLgo4D+ynQAuolQevAdgq8AM6rk0Vo0R7ngQ3UU+qvvNfzCOhKcE4fOu6r39TpIYHT0XsfdDon45puq7WcwFrk7f1XQvVsdPS3Wd+geMPeRN65XqJZdVf9od5Tz/TZ7t3Q7aqzg2avqnfUg2gQO+pT9WGMO+E/CF21m5H0gU8AV4GLwEmgCnwC3gEbwJMkST4elfsHJbIReGbv9uUAAAAASUVORK5CYII=);
background-repeat: no-repeat;
}
.button.external-login.drupal {
background-color: #0f85b6;
}

@ -0,0 +1,22 @@
Package.describe({
name: 'rocketchat:drupal',
version: '0.0.1',
summary: 'RocketChat settings for Drupal oAuth2'
});
Package.onUse(function(api) {
api.versionsFrom('1.0');
api.use('ecmascript');
api.use('service-configuration');
api.use('rocketchat:lib@0.0.1');
api.use('rocketchat:custom-oauth');
// api.use('templating', 'client');
api.addFiles('common.js');
api.addFiles('login-button.css', 'client');
api.addFiles('startup.js', 'server');
api.use('templating', 'client');
});

@ -0,0 +1,14 @@
RocketChat.settings.addGroup('OAuth', function() {
this.section('Drupal', function() {
const enableQuery = {
_id: 'Accounts_OAuth_Drupal',
value: true
};
this.add('Accounts_OAuth_Drupal', false, { type: 'boolean' });
this.add('API_Drupal_URL', '', { type: 'string', public: true, enableQuery, i18nDescription: 'API_Drupal_URL_Description' });
this.add('Accounts_OAuth_Drupal_id', '', { type: 'string', enableQuery });
this.add('Accounts_OAuth_Drupal_secret', '', { type: 'string', enableQuery });
this.add('Accounts_OAuth_Drupal_callback_url', '_oauth/drupal', { type: 'relativeUrl', readonly: true, force: true, enableQuery });
});
});

@ -49,16 +49,6 @@ getEmojiUrlFromName = function(name, extension) {
Blaze.registerHelper('emojiUrlFromName', getEmojiUrlFromName);
function updateEmojiPickerList() {
let html = '';
for (const entry of RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket) {
const renderedEmoji = RocketChat.emoji.packages.emojiCustom.render(`:${ entry }:`);
html += `<li class="emoji-${ entry }" data-emoji="${ entry }">${ renderedEmoji }</li>`;
}
$('.rocket.emoji-list').empty().append(html);
RocketChat.EmojiPicker.updateRecent();
}
deleteEmojiCustom = function(emojiData) {
delete RocketChat.emoji.list[`:${ emojiData.name }:`];
const arrayIndex = RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(emojiData.name);
@ -78,7 +68,7 @@ deleteEmojiCustom = function(emojiData) {
}
}
}
updateEmojiPickerList();
RocketChat.EmojiPicker.updateRecent();
};
updateEmojiCustom = function(emojiData) {
@ -154,7 +144,7 @@ updateEmojiCustom = function(emojiData) {
}
}
updateEmojiPickerList();
RocketChat.EmojiPicker.updateRecent();
};
Meteor.startup(() =>

@ -39,7 +39,6 @@ function getEmojisByCategory(category) {
//set correctPackage here to allow for recent emojis to work properly
if (isSetNotNull(() => RocketChat.emoji.list[`:${ emoji }:`].emojiPackage)) {
const correctPackage = RocketChat.emoji.list[`:${ emoji }:`].emojiPackage;
const image = RocketChat.emoji.packages[correctPackage].render(`:${ emoji }${ tone }:`);
html += `<li class="emoji-${ emoji }" data-emoji="${ emoji }" title="${ emoji }">${ image }</li>`;
@ -126,10 +125,13 @@ Template.emojiPicker.helpers({
emojiList(category) {
const t = Template.instance();
const searchTerm = t.currentSearchTerm.get();
const activeCategory = t.currentCategory.get();
//this will cause the reflow when recent list gets updated
t.recentNeedsUpdate.get();
//clear dynamic categories to prevent duplication issues
if (category === 'recent' || category === 'rocket') {
$(`.${ category }.emoji-list`).empty();
//we only need to replace the active category, since switching tabs resets the filter
if (activeCategory !== category) {
return;
}
if (searchTerm.length > 0) {
@ -263,7 +265,7 @@ Template.emojiPicker.events({
Template.emojiPicker.onCreated(function() {
this.tone = RocketChat.EmojiPicker.getTone();
const recent = RocketChat.EmojiPicker.getRecent();
this.recentNeedsUpdate = new ReactiveVar(false);
this.currentCategory = new ReactiveVar(recent.length > 0 ? 'recent' : 'people');
this.currentSearchTerm = new ReactiveVar('');
@ -276,4 +278,10 @@ Template.emojiPicker.onCreated(function() {
$('.current-tone').addClass(`tone-${ newTone }`);
this.tone = newTone;
};
this.autorun(() => {
if (this.recentNeedsUpdate.get()) {
this.recentNeedsUpdate.set(false);
}
});
});

@ -1,5 +1,3 @@
@import "lesshat.less";
.emoji-picker-icon {
cursor: pointer;
font-size: 18px;
@ -10,7 +8,7 @@
&:hover {
&::before {
.transform(scale(1.2));
transform: scale(1.2);
}
}
}
@ -73,7 +71,7 @@
transition: transform 0.2s ease;
&:hover {
.transform(scale(1.2));
transform: scale(1.2);
background-color: #dddddd;
}
}
@ -123,12 +121,12 @@
top: 25px;
z-index: 1;
transition: transform 0.2s ease, visibility 0.2s ease, opacity 0.2s ease;
.transform(translateY(-20px));
transform: translateY(-20px);
opacity: 0;
visibility: hidden;
&.show {
.transform(translateY(0px));
transform: translateY(0);
opacity: 1;
display: block;
visibility: visible;

@ -1,17 +0,0 @@
// lesshat - The best mixin library in the world
//
// version: v4.1.0 (2016-07-19)
.calc(...) {
@process: ~`(function(a){function c(c,t){var r=");\n",s=e.split(","),l=s[0]+":"+c+"("+(s[1].trim()||0)+r;"start"==t?a="0;\n"+l:a+=l}a=a||8121991;var t="@{state}",e=a;if(8121991==a)return a;switch(t){case"1":c("-webkit-calc","start"),c("-moz-calc"),c("calc");break;case"2":c("-webkit-calc","start"),c("-moz-calc");break;case"3":c("-webkit-calc","start"),c("calc");break;case"4":c("-webkit-calc","start");break;case"5":c("-moz-calc","start"),c("calc");break;case"6":c("-moz-calc","start");break;case"7":c("calc","start")}return a=a.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
@state: 1; -lh-property: @process;
}
.transform(...) {
@process: ~`(function(e){e=e||"none";var r={translate:"px",rotate:"deg",rotate3d:"deg",skew:"deg"};/^\w*\(?[a-z0-9.]*\)?/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,""));for(var t in r)e.indexOf(t)>=0&&(e=e.replace(new RegExp(t+"[\\w]?\\([a-z0-9, %]*\\)"),function(e){var n=/(\d+\.?\d*)(?!\w|%)/g;return"rotate3d"==t&&(n=/,\s*\d+$/),e.replace(n,function(e){return e+r[t]})}));return e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-webkit-transform: @process;
-moz-transform: @process;
-ms-transform: @process;
-o-transform: @process;
transform: @process;
}

@ -1,4 +1,4 @@
/* globals Blaze, isSetNotNull, Template */
/* globals Blaze, Template */
RocketChat.EmojiPicker = {
width: 390,
height: 238,
@ -115,23 +115,31 @@ RocketChat.EmojiPicker = {
window.localStorage.setItem('emoji.recent', this.recent);
RocketChat.emoji.packages.base.emojisByCategory.recent = this.recent;
this.updateRecent();
},
updateRecent() {
const total = RocketChat.emoji.packages.base.emojisByCategory.recent.length;
let html = '';
for (let i = 0; i < total; i++) {
const emoji = RocketChat.emoji.packages.base.emojisByCategory.recent[i];
if (isSetNotNull(() => RocketChat.emoji.list[`:${ emoji }:`])) {
const emojiPackage = RocketChat.emoji.list[`:${ emoji }:`].emojiPackage;
const renderedEmoji = RocketChat.emoji.packages[emojiPackage].render(`:${ emoji }:`);
html += `<li class="emoji-${ emoji }" data-emoji="${ emoji }">${ renderedEmoji }</li>`;
} else {
this.recent = _.without(this.recent, emoji);
}
const instance = Template.instance();
if (instance) {
instance.recentNeedsUpdate.set(true);
} else {
this.refreshDynamicEmojiLists();
}
$('.recent.emoji-list').empty().append(html);
},
refreshDynamicEmojiLists() {
const dynamicEmojiLists = [
RocketChat.emoji.packages.base.emojisByCategory.recent,
RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket
];
dynamicEmojiLists.forEach((category) => {
if (category) {
for (let i = 0; i < category.length; i++) {
const emoji = category[i];
if (!RocketChat.emoji.list[`:${ emoji }:`]) {
category = _.without(category, emoji);
}
}
}
});
}
};

@ -1,6 +1,8 @@
{
"#channel": "#канал",
"0_Errors_Only": "0 - Само Грешки",
"1_Errors_and_Information": "1 - Грешки и Информация",
"2_Erros_Information_and_Debug": "2 - Грешки, Информация и Дебъг",
"403": "Забранен",
"@username": "@потребителско име",
"@username_message": "@потребителско име<message>",
@ -23,6 +25,7 @@
"Accounts_OAuth_Facebook": "Влизана с Facebook профил",
"Accounts_OAuth_Google": "Влизане с Google профил",
"Accounts_RegistrationForm_Public": "Обществен",
"All_channels": "Всички канали",
"All_messages": "Всички съобщения",
"and": "и",
"Application_Name": "Име на Приложение",
@ -38,6 +41,8 @@
"Busy_male": "Зает",
"channel": "канал",
"Channel": "Канал",
"Channels": "Канали",
"Channels_list": "Списък на публични канали",
"Click_here": "Натисни тук",
"close": "затвори",
"Close": "Затвори",
@ -84,6 +89,7 @@
"LDAP_Port": "Порт",
"Leave_room": "Излез от стаята",
"line": "линия",
"List_of_Channels": "Списък с Канали",
"Loading...": "Зареждане...",
"Log_Package": "Покажи пакет",
"Login": "Влез",
@ -96,6 +102,7 @@
"Message_too_long": "Съобщението е твърде дълго",
"Messages": "Съобщения",
"minutes": "Минути",
"More_channels": "Още канали",
"My_Account": "Моя Профил",
"n_messages": "%s съобщения",
"N_new_messages": "%s нови съобщения",
@ -112,6 +119,7 @@
"Online": "На линия",
"Oops!": "Упс",
"Open": "Отвори",
"Password": "Парола",
"People": "Хора",
"Please_add_a_comment": "Добави коментар моля",
"Please_wait": "Моля изчакайте",
@ -145,6 +153,8 @@
"Site_Name": "Име на Сайта",
"Skip": "Прескочи",
"Smarsh_MissingEmail_Email": "Липсваща Електрона поща",
"Stats_Total_Channels": "Общо Канали",
"Stats_Total_Messages_Channel": "Общо Съобщения в Канали",
"Test_Desktop_Notifications": "Изпробвай Известия на работния плот",
"Thank_you_exclamation_mark": "Благодаря!",
"The_server_will_restart_in_s_seconds": "Сървъра ще бъде рестартиран след %s секунди",

@ -17,6 +17,7 @@
"Accessing_permissions": "L'accés als permisos",
"Account_SID": "Compte SID",
"Accounts": "Comptes",
"Accounts_AllowAnonymousAccess": "Permet accés anònim",
"Accounts_AllowDeleteOwnAccount": "Permetre als usuaris eliminar el seu propi compte",
"Accounts_AllowedDomainsList": "Llista de dominis permesos",
"Accounts_AllowedDomainsList_Description": "Llista dels dominis permesos separada per comes ",
@ -62,6 +63,10 @@
"Accounts_OAuth_Custom_Token_Path": "Ruta del token",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token enviat via",
"Accounts_OAuth_Custom_Username_Field": "Camp de nom d'usuari",
"Accounts_OAuth_Drupal": "Activa inici de sessió de Drupal",
"Accounts_OAuth_Drupal_callback_url": "Redirect URI de Drupal oAuth2",
"Accounts_OAuth_Drupal_id": "Client ID de Drupal oAuth2",
"Accounts_OAuth_Drupal_secret": "Client Secret de Drupal oAuth2",
"Accounts_OAuth_Facebook": "Inici de sessió amb Facebook",
"Accounts_OAuth_Facebook_callback_url": "URL de retorn (callback) de Facebook",
"Accounts_OAuth_Facebook_id": "App ID de Facebook",
@ -170,6 +175,8 @@
"API_CORS_Origin": "Origen CORS",
"API_Default_Count": "Comptador per defecte",
"API_Default_Count_Description": "El comptador per defecte per als resultats de les peticions API REST si el consumidor no n'ha especificat cap.",
"API_Drupal_URL": "Adreça URL del servidor de Drupal",
"API_Drupal_URL_Description": "Exemple: https://domini.com (sense la barra final)",
"API_Embed": "Incrusta (embed)",
"API_Embed_Description": "Activa o no les previsualitzacions d'enllaços quan un usuari publica l'enllaç a un web.",
"API_EmbedCacheExpirationDays": "Caducitat de la memòria cau de les incrustacions (en dies)",
@ -182,9 +189,13 @@
"API_Enable_CORS": "Activa CORS",
"API_Enable_Direct_Message_History_EndPoint": "Activa la consulta de l'historial de missatges directes",
"API_Enable_Direct_Message_History_EndPoint_Description": "Això activa el `/api/v1/im.history.others` que permet veure missatges directes enviats per altres usuaris tot i no formar-ne part.",
"API_Enable_Shields": "Activa escuts",
"API_Enable_Shields_Description": "Activa els escuts disponibles a `/api/v1/shields.svg`",
"API_GitHub_Enterprise_URL": "URL del servidor",
"API_GitHub_Enterprise_URL_Description": "Exemple: http://domain.com (sense la barra final)",
"API_Gitlab_URL": "URL de GitLab",
"API_Shield_Types": "Tipus d'escut",
"API_Shield_Types_Description": "Tipus d'escut que s'activaran, com a llista separada per comes. Triar entre `online`, `channel` o `*` per a tots",
"API_Token": "API Token",
"API_Upper_Count_Limit": "Nombre màxim de registres",
"API_Upper_Count_Limit_Description": "Quin és el nombre màxim de registres que la API REST pot retornar (si no és il·limitat)?",
@ -406,6 +417,7 @@
"Desktop_Notifications_Enabled": "Les notificacions d'escriptori estan activades",
"Direct_message_someone": "Envia un missatge directe a algú",
"Direct_Messages": "Missatges directes",
"Disable_Notifications": "Desactiva notificacions",
"Disable_two-factor_authentication": "Desactiva l'autenticació de dos factors",
"Display_offline_form": "Mostra el formulari de fora de línia",
"Displays_action_text": "Mostra text de l'acció",
@ -618,6 +630,7 @@
"Give_the_application_a_name_This_will_be_seen_by_your_users": "Bateja l'aplicació. El nom escollit serà visible als usuaris.",
"Global": "Global",
"GoogleCloudStorage": "Emmagatzematge Google Cloud",
"GoogleNaturalLanguage_ServiceAccount_Description": "Arxiu JSON amb la clau del compte de servei (\"Service account key\"). Pots trobar més informació [aquí](https://cloud.google.com/natural-language/docs/common/auth#set_up_a_service_account)",
"GoogleTagManager_id": "ID de Google Tag Manager",
"Guest_Pool": "Llista de clients",
"Hash": "Hash",
@ -633,6 +646,7 @@
"Hide_room": "Oculta sala",
"Hide_Room_Warning": "Segur que voleu ocultar la sala \"%s\"?",
"Hide_roles": "Amaga rols",
"Hide_Unread_Room_Status": "Amaga l'estat de sales no llegides",
"Hide_usernames": "Oculta els noms d'usuari",
"Highlights": "Ressalta",
"Highlights_How_To": "Per ser notificat quan algú esmenta una paraula o frase, afegeix-la aquí. Es poden separar les paraules o frases amb comes. No es distingeix entre majúscules i minúscules.",
@ -725,6 +739,8 @@
"Integration_Retry_Count_Description": "Quantes vegades s'ha de reintentar la integració si la petició a l'adreça URL falla?",
"Integration_Retry_Delay": "Temps de reintent",
"Integration_Retry_Delay_Description": "Quin algorisme de retard de reintent s'ha d'utilitzar? <code class=\"inline\">10^x</code> o <code class=\"inline\">2^x</code> o <code class=\"inline\">x*2</code>",
"Integration_Run_When_Message_Is_Edited": "Executa en edicions",
"Integration_Run_When_Message_Is_Edited_Description": "Aquesta integració s'ha d'executar quan el missatge s'edita? Desactivar aquesta opció farà que la integració només s'executi en <strong>missatges nous</strong> .",
"Integration_Word_Trigger_Placement": "Posició indeterminada de paraula",
"Integration_Word_Trigger_Placement_Description": "S'hauria d'activar el disparador quan la paraula es troba en un lloc de la frase fora del començament?",
"Integration_updated": "La integració s'ha actualitzat.",
@ -782,6 +798,7 @@
"Jitsi_Enable_Channels": "Activa als canals",
"join": "Unir-se",
"Join_audio_call": "Unir-se a la trucada",
"Join_Chat": "Uneix-te al xat",
"Join_default_channels": "Unir-se als canals predeterminats",
"Join_the_Community": "Uneix-te a la comunitat",
"Join_the_given_channel": "Unir-se al canal proporcionat",
@ -962,6 +979,9 @@
"Message_AllowUnrecognizedSlashCommand": "Permet /comandes no reconegudes",
"Message_AlwaysSearchRegExp": "Sempre cercar utilitzant RegExp",
"Message_AlwaysSearchRegExp_Description": "Recomanem activar-ho si el teu idioma no està suportat per la <a target=\"_blank\" href=\"https://docs.mongodb.org/manual/reference/text-search-languages/#text-search-languages\">cerca de text MongoDB</a>.",
"Message_Attachments": "Adjunts al missatge",
"Message_Attachments_GroupAttach": "Agrupa els botons d'adjuntar",
"Message_Attachments_GroupAttachDescription": "Això uneix les icones en un menú desplegable. Ocupen menys espai a la pantalla.",
"Message_AudioRecorderEnabled": "Gravadora d'àudio activa",
"Message_AudioRecorderEnabledDescription": "Requereix que els arxius de tipus 'audio/wav' siguin un tipus de fitxer vàlid dins les opcions de 'Pujar arxius'.",
"Message_BadWordsFilterList": "Afegir paraulotes a la llista negra",
@ -1065,6 +1085,7 @@
"Nothing_found": "No s'ha trobat res",
"Notification_Duration": "Duració de la notificació",
"Notifications": "Notificacions",
"Notifications_Muted_Description": "Si esculls silenciar-ho tot, no veuràs la sala destacada a la llista quan hi hagi nous missatges, excepte si són mencions. Silenciar les notificacions sobreescriurà les opcions de notificació.",
"Notify_all_in_this_room": "Notifica a tothom d'aquest canal",
"Notify_active_in_this_room": "Notifica als usuaris actius d'aquesta sala",
"Num_Agents": "# d'agents",
@ -1207,6 +1228,7 @@
"Register": "Crea un compte nou",
"Registration": "Registre",
"Registration_Succeeded": "Registre reeixit",
"Register_or_login_to_send_messages": "Registra't o identifica't per enviar missatges",
"Registration_via_Admin": "Registre via Admin",
"Regular_Expressions": "Expressions regulars",
"Release": "Llançament",
@ -1322,6 +1344,7 @@
"Sending": "Enviant...",
"Served_By": "Servit per",
"Service": "Servei",
"Service_account_key": "Service account key",
"Set_as_moderator": "Fes-lo moderador",
"Set_as_owner": "Fes-lo propietari",
"Settings": "Configuració",
@ -1522,13 +1545,14 @@
"UI_DisplayRoles": "Mostra rols",
"UI_Merge_Channels_Groups": "Uneix grups privats amb canals",
"UI_Use_Name_Avatar": "Utilitza les inicials del nom complet per generar l'avatar per defecte",
"UI_Use_Real_Name": "Utilitza el nom real",
"Unarchive": "Desarxiva",
"Unblock_User": "Desbloqueja usuari",
"Unmute_someone_in_room": "Torna a donar veu a algú de la sala",
"Unmute_user": "Dóna veu a l'usuari",
"Unnamed": "Sense nom",
"Unpin_Message": "Desfixa el missatge",
"Unread_Alert": "Alerta de no llegit",
"Unread_Tray_Icon_Alert": "Icona d'alerta de no llegits a la safata",
"Unread_Messages": "Missatges no llegits",
"Unread_Rooms": "Sales no llegides",
"Unread_Rooms_Mode": "Mode de sales no llegides",

@ -17,6 +17,7 @@
"Accessing_permissions": "Přístup k oprávnění",
"Account_SID": "SID účtu",
"Accounts": "Účty",
"Accounts_AllowAnonymousAccess": "Povolit anonymní přístup",
"Accounts_AllowDeleteOwnAccount": "Povolit uživatelům odstranit vlastní účet",
"Accounts_AllowedDomainsList": "Seznam povolených domén",
"Accounts_AllowedDomainsList_Description": "Čárkami oddělený seznam povolených domén",
@ -62,6 +63,10 @@
"Accounts_OAuth_Custom_Token_Path": "Cesta k tokenu",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token odesílány přes",
"Accounts_OAuth_Custom_Username_Field": "Pole uživatelské jméno",
"Accounts_OAuth_Drupal": "Povolit Drupal přihlášení",
"Accounts_OAuth_Drupal_callback_url": "Drupal oAuth2 URI Přesměrování",
"Accounts_OAuth_Drupal_id": "Drupal oAuth2 ID klienta",
"Accounts_OAuth_Drupal_secret": "Drupal oAuth2 Secret klienta",
"Accounts_OAuth_Facebook": "Facebook Přihlášení",
"Accounts_OAuth_Facebook_callback_url": "Facebook Callback URL",
"Accounts_OAuth_Facebook_id": "Facebook App Id",
@ -170,6 +175,8 @@
"API_CORS_Origin": "CORS Origin",
"API_Default_Count": "Výchozí počet",
"API_Default_Count_Description": "Výchozí počet výsledků v REST API pokud není zažádáno konkrétní číslo",
"API_Drupal_URL": "Drupal URL Serveru",
"API_Drupal_URL_Description": "Například: https://domain.com (bez lomítka na konci)",
"API_Embed": "Náhled vložených odkazů",
"API_Embed_Description": "Zda zobrazit náhled stránky když uživatel pošle odkaz",
"API_EmbedCacheExpirationDays": "Počet dní expirace cache embed",
@ -182,9 +189,13 @@
"API_Enable_CORS": "Povolit CORS",
"API_Enable_Direct_Message_History_EndPoint": "Povolit Endpoint přímých zpráv",
"API_Enable_Direct_Message_History_EndPoint_Description": "Povolí endpoint `/api/v1/im.history.others` přes který lze stahovat přímé zprávy mezi všemi uživateli.",
"API_Enable_Shields": "Povolit sdílecí ikony",
"API_Enable_Shields_Description": "Ikony dostupné na adrese `/api/v1/shields.svg`",
"API_GitHub_Enterprise_URL": "Adresa URL serveru",
"API_GitHub_Enterprise_URL_Description": "Příklad: http://domain.com (bez lomítka na konci)",
"API_Gitlab_URL": "GitLab URL",
"API_Shield_Types": "Typy ikon",
"API_Shield_Types_Description": "Čárkou oddělený seznam povolených typů. Na výběr z `online`, `channel` nebo `*` pro všechny.",
"API_Token": "API Token",
"API_Upper_Count_Limit": "Maximální počet",
"API_Upper_Count_Limit_Description": "Kolik nejvíce záznamů smí REST API vrátit (pokud není limitovaná)",
@ -245,6 +256,7 @@
"Back_to_integration_detail": "Zpět na detail integrace",
"Back_to_login": "Zpět na přihlašovací formulář",
"Back_to_permissions": "Zpět na práva",
"Backup_codes": "Záložní kódy",
"Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Beta funkcionalita. Videohovory musí být povoleny.",
"Block_User": "Blokovat uživatele",
"Body": "Obsah",
@ -405,6 +417,8 @@
"Desktop_Notifications_Enabled": "Oznámení na ploše jsou povolena",
"Direct_message_someone": "Přímá zpráva někomu",
"Direct_Messages": "Přímé zprávy",
"Disable_Notifications": "Zakázat notifikace",
"Disable_two-factor_authentication": "Zakázat dvoufázové ověření",
"Display_offline_form": "Zobrazit offline formulář",
"Displays_action_text": "Zobrazuje text akce",
"Do_you_want_to_change_to_s_question": "Chcete změnit na <strong>%s?</strong>",
@ -447,10 +461,12 @@
"Empty_title": "Prázdný název",
"Enable": "Povolit",
"Enable_Desktop_Notifications": "Aktivovat oznámení na ploše",
"Enable_two-factor_authentication": "Povolit dvoufázové ověření",
"Enabled": "Povoleno",
"Enable_Svg_Favicon": "Povolit SVG favikonu",
"Encrypted_message": "Šifrovaná zpráva",
"End_OTR": "Ukončit konverzaci mimo záznam",
"Enter_authentication_code": "Zadejte autentizační kód",
"Enter_Alternative": "Alternativní mód (odesílat po stisku Enter + Ctrl/Alt/Shift/CMD)",
"Enter_a_regex": "Zadejte regulární výraz",
"Enter_a_room_name": "Zadejte název místnosti",
@ -614,6 +630,7 @@
"Give_the_application_a_name_This_will_be_seen_by_your_users": "Pojmenujte jak se bude aplikace jmenovat pro Vaše uživatele.",
"Global": "Globální",
"GoogleCloudStorage": "Google Cloud Storage",
"GoogleNaturalLanguage_ServiceAccount_Description": "JSON klíč účtu služby. Více informací naleznete [zde](https://cloud.google.com/natural-language/docs/common/auth#set_up_a_service_account)",
"GoogleTagManager_id": "ID Google tag manageru",
"Guest_Pool": "Skupina hostů",
"Hash": "Hash",
@ -629,6 +646,7 @@
"Hide_room": "Skrýt místnost",
"Hide_Room_Warning": "Jste si jisti, že chcete skrýt místnost \"%s\"?",
"Hide_roles": "Schovat role",
"Hide_Unread_Room_Status": "Schovat stav nepřečtených místností",
"Hide_usernames": "Skrýt uživatelská jména",
"Highlights": "Klíčová slova",
"Highlights_How_To": "Chcete-li být upozorněni, když někdo zmíní slovo nebo frázi, přidejte jej sem. Můžete oddělit slova nebo fráze čárkami. Velikost písmen nehraje roli",
@ -721,6 +739,8 @@
"Integration_Retry_Count_Description": "Kolikrát by se integrace měla znova pokusit volat URL pokud byl první pokus neúspěšný?",
"Integration_Retry_Delay": "Čas prodlení opakování",
"Integration_Retry_Delay_Description": "Jaký algoritmus prodlení by se měl použít?<code class=\"inline\">10^x</code>, <code class=\"inline\">2^x</code> nebo <code class=\"inline\">x*2</code>",
"Integration_Run_When_Message_Is_Edited": "Spustit při editaci",
"Integration_Run_When_Message_Is_Edited_Description": "Měla by být integrace spuštěna po editaci zprávy? Pokud volbu vypnete, integrace se bude spouštět pouze pro <strong>nové</strong> zprávy.",
"Integration_Word_Trigger_Placement": "Přepisování slov kdekoliv",
"Integration_Word_Trigger_Placement_Description": "Mělo by se vyvolat pokud je slovo umístěno jinde než na začátku?",
"Integration_updated": "Integrace byla aktualizována",
@ -740,6 +760,7 @@
"Invalid_room_name": "<strong>%s</strong> není platné jméno místnosti,<br/> použijte pouze písmena, číslice a pomlčky",
"Invalid_secret_URL_message": "Adresa URL je neplatná.",
"Invalid_setting_s": "Neplatné nastavení: %s",
"Invalid_two_factor_code": "Neplatný dvoufázový kód",
"invisible": "neviditelný",
"Invisible": "Neviditelný",
"Invitation": "Pozvánka",
@ -777,6 +798,7 @@
"Jitsi_Enable_Channels": "Povolit v místnostech",
"join": "Připojit",
"Join_audio_call": "Připojit k hovoru",
"Join_Chat": "Připojit k chatu",
"Join_default_channels": "Připojit se k výchozím místnostem",
"Join_the_Community": "Zapojte se do komunity",
"Join_the_given_channel": "Přidejte se k dané místnosti",
@ -924,6 +946,7 @@
"Mailer_body_tags": "Je <b>nutné</b> použít [unsubscribe] pro vložení odkazu na odhlášení. <br/> Můžete také použít [name], [fname], [lname] pro uživatelské jméno, křestí jméno a příjmen nebo [email] pro e-mail uživatele.",
"Mailing": "Mailing",
"Make_Admin": "Změnit na Správce",
"Make_sure_you_have_a_copy_of_your_codes": "Pečlivě is uschovejte kopii svých kódů: __codes__ Pokud ztratíte přístup ke své autentizační aplikaci, můžete jeden z nich použít k přihlášení.",
"Manager_added": "Manažer přidán",
"Manager_removed": "Manažer odstraněn",
"Managing_assets": "Správa datových zdrojů",
@ -956,6 +979,9 @@
"Message_AllowUnrecognizedSlashCommand": "Povolit nerozpoznané lomítkové příkazy",
"Message_AlwaysSearchRegExp": "Vždy hledat pomocí regulárních výrazů",
"Message_AlwaysSearchRegExp_Description": "Doporučujeme nastavit `Ano` pokud Váš jazyk není podporován v <a target=\"_blank\" href=\"https://docs.mongodb.org/manual/reference/text-search-languages/#text-search-languages\">textového vyhledávání MongoDB</a> .",
"Message_Attachments": "Přílohy zprávy",
"Message_Attachments_GroupAttach": "Sjednotit tlačítka přílohy",
"Message_Attachments_GroupAttachDescription": "Zobrazi tlačítka přílohy jako rozklikávací menu, zabere méně místa na obrazovce",
"Message_AudioRecorderEnabled": "Záznam zvuku povolen",
"Message_AudioRecorderEnabledDescription": "Je třeba mít povolené `audio/wav` soubory v nabídce 'Nahrání souboru'",
"Message_BadWordsFilterList": "Přidat sprostá slova na černou listinu",
@ -1059,6 +1085,7 @@
"Nothing_found": "Nic nalezeno",
"Notification_Duration": "Délka zobrazení oznámení",
"Notifications": "Oznámení",
"Notifications_Muted_Description": "Pokud ztišíte všechno, neuvidíte zvýrazněné místnosti s novými zprávami, krom zmínek. Ztišení notifikací přetěží nastavení notifikací v jednotlivých místnostech.",
"Notify_all_in_this_room": "Oznámit všem v této místnosti",
"Notify_active_in_this_room": "Notifikovat aktivní uživatele v místnosti",
"Num_Agents": "# Operátorů",
@ -1095,6 +1122,7 @@
"optional": "volitelný",
"Use_minor_colors": "Použít nevýraznou barevnou baletu (ve výchozím stavu podědí výraznou paletu)",
"or": "nebo",
"Open_your_authentication_app_and_enter_the_code": "Otevřete autentizační aplikaci a zadejte vygenerovaný kód. Můžete použít jeden ze svých záložních kódů.",
"Order": "Objednat",
"OS_Arch": "Architektura OS",
"OS_Cpus": "Počet CPU OS",
@ -1196,9 +1224,11 @@
"Refresh_oauth_services": "Obnovit služby OAuth",
"Refresh_keys": "Obnovit klíče",
"Refresh_your_page_after_install_to_enable_screen_sharing": "Po instalaci obnovte stránku aby sdílení stránky fungovalo",
"Regenerate_codes": "Přegenerovat záložní kódy",
"Register": "Zaregistrovat nový účet",
"Registration": "Registrace",
"Registration_Succeeded": "Registrace úspěšná",
"Register_or_login_to_send_messages": "Pro odeslání zpráv je třeba se zaregistrovat nebo přihlásit",
"Registration_via_Admin": "Registrace přes Admin",
"Regular_Expressions": "Regulární výrazy",
"Release": "Verze",
@ -1276,6 +1306,7 @@
"Save_to_enable_this_action": "Uložte pro povolení akce",
"Saved": "Uloženo",
"Saving": "Ukládání",
"Scan_QR_code": "V autentizační aplikace jako Google Authenticator, Authy nebo Duo naskenujte QR kód. Aplikace vám poté zobrazí 6-ti místný kód, který zadejte níže.",
"Scope": "Rozsah",
"Screen_Share": "Sdílení obrazovky",
"Script_Enabled": "Skript Povolen",
@ -1285,6 +1316,7 @@
"Search_Private_Groups": "Vyhledávání soukromých skupin",
"seconds": "sekundy",
"Secret_token": "Tajný token",
"Security": "Zabezpečení",
"Select_a_department": "Vyberte oddělení",
"Select_a_user": "Vyberte uživatele",
"Select_an_avatar": "Vyberte avatar",
@ -1312,6 +1344,7 @@
"Sending": "Odesílání ...",
"Served_By": "Poskytovatel",
"Service": "Služba",
"Service_account_key": "Klíč účty služby",
"Set_as_moderator": "Nastavit jako moderátora",
"Set_as_owner": "Nastavit jako vlastníka",
"Settings": "Nastavení",
@ -1478,6 +1511,10 @@
"This_is_a_push_test_messsage": "Toto je testovací notifikace",
"This_room_has_been_archived_by__username_": "Tato místnost byla archivována uživatelem __username__",
"This_room_has_been_unarchived_by__username_": "Tato místnost byla úspěšně odarchivována uživatelem __username__",
"Two-factor_authentication": "Dvoufázové ověření",
"Two-factor_authentication_disabled": "Dvoufázová ověření zakázáno",
"Two-factor_authentication_enabled": "Dvoufázové ověření povoleno",
"Two-factor_authentication_is_currently_disabled": "Dvoufázová ověření je momentálně zakázáno",
"Thursday": "Čtvrtek",
"Time_in_seconds": "Čas v sekundách",
"Title": "Název",
@ -1508,13 +1545,14 @@
"UI_DisplayRoles": "Zobrazit Role",
"UI_Merge_Channels_Groups": "Sloučit privátní skupiny s místnostmi",
"UI_Use_Name_Avatar": "Použít iniciály celého jména uživatele pro výchozí avatar",
"UI_Use_Real_Name": "Použít skutečné jméno",
"Unarchive": "Zrušit archivaci",
"Unblock_User": "Odblokovat uživatele",
"Unmute_someone_in_room": "Zrušit ztlumení někoho v místnosti",
"Unmute_user": "Zrušit ztlumení uživatele",
"Unnamed": "Nepojmenovaný",
"Unpin_Message": "Odepnout Zprávu",
"Unread_Alert": "Nepřečtené upozornění",
"Unread_Tray_Icon_Alert": "Ikona v oznamovací oblasti upozorňuje na nepřečtené zprávy",
"Unread_Messages": "Nepřečtěné zprávy",
"Unread_Rooms": "Nepřečtené místnosti",
"Unread_Rooms_Mode": "Mód Nepřečtených místností",
@ -1599,6 +1637,7 @@
"Verification_Email_Subject": "[Site_Name] - Potvrďte svůj účet",
"Verification_Email": "Klikněte na <a href=\"[Verification_Url]\">tento odkaz</a> pro potvrzení svého účtu.",
"Verified": "Ověřený",
"Verify": "Ověřit",
"Version": "Verze",
"Video_Chat_Window": "Video chat",
"Video_Conference": "Video konference",
@ -1653,6 +1692,7 @@
"You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Webhooky můžete použít pro jednoduchou integraci s Vaším CRM",
"You_cant_leave_a_livechat_room_Please_use_the_close_button": "Livechat místnost nelze opustit. Použijte prosím tlačítko zavřít.",
"You_have_been_muted": "Byli jste ztišeni a nemůžete v této místnosti mluvit",
"You_have_n_codes_remaining": "Zbývá vám __number__ kódů.",
"You_have_not_verified_your_email": "Neověřili jste svůj e-mail.",
"You_have_successfully_unsubscribed": "Úspěšně jste se odhlásili z našeho seznamu.",
"You_must_join_to_view_messages_in_this_channel": "Pro zobrazení zpráv v této místnosti je třeba se připojit",

@ -1127,7 +1127,6 @@
"Unmute_user": "Benutzern das Chatten erlauben ",
"Unnamed": "Unbenannt",
"Unpin_Message": "Nachicht nicht mehr fixieren",
"Unread_Alert": "Über Ungelesenes benachrichtigen",
"Unread_Rooms": "Ungelesene Räume",
"Unread_Rooms_Mode": "Ungelesene Räume aufgelistet anzeigen ",
"Unstar_Message": "Markierung entfernen",

@ -62,6 +62,10 @@
"Accounts_OAuth_Custom_Token_Path": "Pfad des Token",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token gesendet über",
"Accounts_OAuth_Custom_Username_Field": "Benutzernamen Feld",
"Accounts_OAuth_Drupal": "Login mit Drupal aktiviert",
"Accounts_OAuth_Drupal_callback_url": "Drupal oAuth Redirect Url",
"Accounts_OAuth_Drupal_id": "Drupal oAuth2 Client ID",
"Accounts_OAuth_Drupal_secret": "Drupal oAuth2 Client Schlüssel",
"Accounts_OAuth_Facebook": "Anmeldung über Facebook erlauben",
"Accounts_OAuth_Facebook_callback_url": "Facebook-Callback-URL",
"Accounts_OAuth_Facebook_id": "Facebook-App-ID",
@ -155,25 +159,35 @@
"Analytics_features_messages_Description": "Zeichnet benutzerdefinierte Ereignisse im Zusammenhang mit Aktionen eines Nutzer auf Nachrichten auf.",
"Analytics_features_rooms_Description": "Zeichnet benutzerdefinierte Ereignisse im Zusammenhang mit Aktionen in einem Kanal oder einer Gruppe (erstellen, verlassen, löschen) auf.",
"Analytics_features_users_Description": "Zeichnet benutzerdefinierte Ereignisse (Passwort-Reset-Zeiten, Profilbild ändern, etc) auf.",
"Analytics_Google": "Google Analytics",
"Analytics_Google_id": "Tracking ID",
"and": "und",
"And_more": "Und __length__ mehr",
"Animals_and_Nature": "Tiere & Natur",
"Announcement": "Ankündigung",
"API": "API",
"API_Allow_Infinite_Count_Description": "Erlaube Rückgabe von REST API Ergebnissen in einem einzigen Abruf",
"API_Analytics": "Analytics",
"API_CORS_Origin": "CORS Origin",
"API_Default_Count": "Standard Anzahl",
"API_Default_Count_Description": "Anzahl an Ergebnissen von REST API Anfragen wenn keine Anzahl übergeben wurde.",
"API_Drupal_URL": "Drupal Server URL",
"API_Drupal_URL_Description": "Beispiel: https://domain.de (ohne schließenden /)",
"API_Embed": "Einbetten",
"API_Embed_Description": "Eingebettete Link Vorschau für Links die von Benutzern gepostet wurden aktiv.",
"API_EmbedDisabledFor": "Einbettungen für Benutzer deaktivieren",
"API_EmbedDisabledFor_Description": "Durch Kommata getrennte Liste von Benutzernamen",
"API_EmbedIgnoredHosts": "Ignorierte Hosts einbetten",
"API_EmbedIgnoredHosts_Description": "Kommagetrennte Liste von Hosts oder CIDR-Adressen, z. B. localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Sichere Ports",
"API_EmbedSafePorts_Description": "Kommagetrennte Liste der Ports, für die eine Vorschau erlaubt ist.",
"API_Enable_CORS": "Aktiviere CORS",
"API_GitHub_Enterprise_URL": "Server-URL",
"API_GitHub_Enterprise_URL_Description": "Beispiel: http://domain.com (ohne Schrägstrich am Ende)",
"API_Gitlab_URL": "GitLab-URL",
"API_Token": "API-Token",
"API_Upper_Count_Limit": "Max. Anzahl an Einträgen",
"API_Upper_Count_Limit_Description": "Max. Anzahl an Einträgen die die REST API zurückliefen soll (sofern ohne Einschränkung)? ",
"API_User_Limit": "User Limit für das Hinzufügen aller Benutzer auf Kanal",
"API_Wordpress_URL": "Wordpress-URL",
"Apiai_Key": "Api.ai-Schlüssel",
@ -205,6 +219,9 @@
"AutoLinker_Urls_TLD": "AutoLinker TLD-URLs",
"AutoLinker_Urls_www": "AutoLinker \"www\"-URLs",
"AutoLinker_UrlsRegExp": "AutoLinker RegExp für URLs",
"Automatic_Translation": "Automatische Übersetzung",
"Auto_Translate": "Auto-Übersetzung",
"AutoTranslate_Enabled": "Aktiviere die Automatische Übersetzung",
"Available": "Verfügbar",
"Available_agents": "Verfügbare Agenten",
"Avatar": "Profilbild",
@ -235,18 +252,26 @@
"busy_male": "beschäftigt",
"Busy_male": "Beschäftigt",
"by": "durch",
"Content": "Inhalt",
"cache_cleared": "Zwischenspeicher gelöscht",
"Cancel": "Abbrechen",
"Cancel_message_input": "Abbrechen",
"Cannot_invite_users_to_direct_rooms": "Benutzer können nicht in private Nachrichtenräume eingeladen werden.",
"CAS_button_color": "Hintergrundfarbe des Login-Buttons",
"CAS_button_label_color": "Farbe des Login-Button-Texts",
"CAS_button_label_text": "Text des Login-Buttons",
"CAS_enabled": "Aktiviert",
"CAS_popup_height": "Höhe des Login Pop Up",
"CAS_popup_width": "Breite des Login Pop Up",
"CAS_Sync_User_Data_Enabled": "Benutzerdaten immer synchronisieren",
"CDN_PREFIX": "CDN-Präfix",
"Certificates_and_Keys": "Zertifikate und Schlüssel",
"Changing_email": "E-Mail-Adresse ändern",
"Change_Room_Type": "Ändere den Raum Typ",
"channel": "Kanal",
"Channel": "Kanal",
"Channel_already_exist": "Der Kanal '#%s' ist bereits vorhanden.",
"Channel_created": "Channel `#%s` angelegt.",
"Channel_already_Unarchived": "Kanal mit dem Namen '#%s' ist bereits im unarchivierten Zustand",
"Channel_Archived": "Kanal mit dem Namen '#%s' wurde erfolgreich archiviert",
"Channel_doesnt_exist": "Der Kanal `#%s` existiert nicht.",
@ -264,10 +289,12 @@
"Choose_messages": "Nachrichten auswählen",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "Wählen Sie den Alias, der vor dem Benutzernamen in den Nachrichten angezeigt wird.",
"Choose_the_username_that_this_integration_will_post_as": "Wählen Sie den Benutzernamen, der die Integration veröffentlicht.",
"clear": "löschen",
"clear_cache_now": "Zwischenspeicher jetzt leeren",
"Clear_all_unreads_question": "Möchten Sie alle ungelesenen Nachrichten löschen?",
"Click_here": "Hier klicken",
"Client_ID": "Client-ID",
"Client_Secret": "Client-Secret",
"Client_Secret": "Client-Schlüssel",
"Clients_will_refresh_in_a_few_seconds": "Clients werden in wenigen Sekunden aktualisiert",
"close": "Schließen",
"Close": "Schließen",
@ -293,6 +320,8 @@
"Create_new": "Neu erstellen",
"Created_at": "Erstellt am",
"Created_at_s_by_s": "Erstellt am <strong>%s</strong> von <strong>%s</strong>",
"CROWD_Reject_Unauthorized": "Unauthorisierte ablehnen.",
"CRM_Integration": "CRM Integration",
"Current_Chats": "Aktuelle Chats",
"Custom": "Benutzerdefiniert",
"Custom_Emoji": "Benutzerdefinierte Emoji",
@ -380,6 +409,7 @@
"Enter_a_regex": "Regex eingeben",
"Enter_a_room_name": "Raumnamen eingeben",
"Enter_a_username": "Benutzernamen eingeben",
"Enter_Behaviour": "Verhalten der Enter-Taste:",
"Enter_name_here": "Namen hier eingeben",
"Enter_to": "Enter-Taste: ",
"Error": "Fehler",
@ -1042,7 +1072,7 @@
"Selected_agents": "Ausgewählte Agenten",
"Send": "Senden",
"Send_a_message": "Eine Nachricht schicken",
"Send_a_test_mail_to_my_user": "Eine Test-E-Mail an die Benutzer senden",
"Send_a_test_mail_to_my_user": "Eine Test-E-Mail an mich senden",
"Send_a_test_push_to_my_user": "Eine Test-Push-Nachricht an mich senden",
"Send_confirmation_email": "Bestätigungsmail versenden",
"Send_data_into_RocketChat_in_realtime": "Daten in Rocket.Chat in Echtzeit senden.",
@ -1059,7 +1089,7 @@
"Sending": "Senden...",
"Service": "Service",
"Set_as_moderator": "Zum Moderator ernennen",
"Set_as_owner": "zum Besitzer machen",
"Set_as_owner": "Zum Besitzer machen",
"Settings": "Einstellungen",
"Settings_updated": "Die Einstellungen wurden aktualisiert.",
"Share_Location_Title": "Standort teilen?",
@ -1203,7 +1233,6 @@
"Unmute_user": "Benutzern das Chatten erlauben ",
"Unnamed": "Unbenannt",
"Unpin_Message": "Nachicht nicht mehr anheften",
"Unread_Alert": "Über Ungelesenes benachrichtigen",
"Unread_Rooms": "Ungelesene Räume",
"Unread_Rooms_Mode": "Ungelesene Räume aufgelistet anzeigen ",
"Unstar_Message": "Markierung entfernen",

@ -47,7 +47,8 @@
"Accounts_OAuth_Custom_Enable": "Καθιστώ ικανό",
"Accounts_OAuth_Custom_id": "Ταυτότητα",
"Accounts_OAuth_Custom_Identity_Path": "Path ταυτότητα",
"Accounts_OAuth_Custom_Login_Style": "Είσοδος Style",
"Accounts_OAuth_Custom_Login_Style": "Τρόπος Εισόδου",
"Accounts_OAuth_Custom_Merge_Users": "Συγχώνευση χρηστ",
"Accounts_OAuth_Custom_Secret": "Μυστικό",
"Accounts_OAuth_Custom_Token_Path": "Token Path",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token αποστέλλονται μέσω",
@ -71,8 +72,8 @@
"Accounts_OAuth_Google_callback_url": "Google επανάκλησης URL",
"Accounts_OAuth_Google_id": "Google Id",
"Accounts_OAuth_Google_secret": "Google Secret",
"Accounts_OAuth_Linkedin": "LinkedIn Login",
"Accounts_OAuth_Linkedin_callback_url": "Linkedin επανάκλησης URL",
"Accounts_OAuth_Linkedin": "LinkedIn Είσοδος",
"Accounts_OAuth_Linkedin_callback_url": "Linkedin URL Επανάκλησης",
"Accounts_OAuth_Linkedin_id": "LinkedIn Id",
"Accounts_OAuth_Linkedin_secret": "LinkedIn Secret",
"Accounts_OAuth_Meteor": "Meteor Login",

@ -17,6 +17,8 @@
"Accessing_permissions": "Accessing permissions",
"Account_SID": "Account SID",
"Accounts": "Accounts",
"Accounts_AllowAnonymousRead": "Allow anonymous read",
"Accounts_AllowAnonymousWrite": "Allow anonymous write",
"Accounts_AllowDeleteOwnAccount": "Allow users to delete own account",
"Accounts_AllowedDomainsList": "Allowed Domains List",
"Accounts_AllowedDomainsList_Description": "Comma-separated list of allowed domains",
@ -34,6 +36,7 @@
"Accounts_BlockedUsernameList": "Blocked Username List",
"Accounts_BlockedUsernameList_Description": "Comma-separated list of blocked usernames (case-insensitive)",
"Accounts_CustomFields_Description": "Should be a valid JSON where keys are the field names containing a dictionary of field settings. Example:<br/><code>{\n\"role\": {\n\"type\": \"select\",\n\"defaultValue\": \"student\",\n\"options\": [\"teacher\", \"student\"],\n\"required\": true,\n\"modifyRecordField\": {\n\"array\": true,\n\"field\": \"roles\"\n}\n},\n\"twitter\": {\n\"type\": \"text\",\n\"required\": true,\n\"minLength\": 2,\n\"maxLength\": 10\n}\n}</code> ",
"Accounts_DefaultUsernamePrefixSuggestion": "Default username prefix suggestion",
"Accounts_denyUnverifiedEmail": "Deny unverified email",
"Accounts_EmailVerification": "Email Verification",
"Accounts_EmailVerification_Description": "Make sure you have correct SMTP settings to use this feature",
@ -62,6 +65,10 @@
"Accounts_OAuth_Custom_Token_Path": "Token Path",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token Sent Via",
"Accounts_OAuth_Custom_Username_Field": "Username field",
"Accounts_OAuth_Drupal": "Drupal Login Enabled",
"Accounts_OAuth_Drupal_callback_url": "Drupal oAuth2 Redirect URI",
"Accounts_OAuth_Drupal_id": "Drupal oAuth2 Client ID",
"Accounts_OAuth_Drupal_secret": "Drupal oAuth2 Client Secret",
"Accounts_OAuth_Facebook": "Facebook Login",
"Accounts_OAuth_Facebook_callback_url": "Facebook Callback URL",
"Accounts_OAuth_Facebook_id": "Facebook App Id",
@ -170,6 +177,8 @@
"API_CORS_Origin": "CORS Origin",
"API_Default_Count": "Default Count",
"API_Default_Count_Description": "The default count for REST API results if the consumer did not provided any.",
"API_Drupal_URL": "Drupal Server URL",
"API_Drupal_URL_Description": "Example: https://domain.com (excluding trailing slash)",
"API_Embed": "Embed Link Previews",
"API_Embed_Description": "Whether embedded link previews are enabled or not when a user posts a link to a website.",
"API_EmbedCacheExpirationDays": "Embed cache expiration days",
@ -410,6 +419,7 @@
"Desktop_Notifications_Enabled": "Desktop Notifications are Enabled",
"Direct_message_someone": "Direct message someone",
"Direct_Messages": "Direct Messages",
"Disable_Notifications": "Disable Notifications",
"Disable_two-factor_authentication": "Disable two-factor authentication",
"Display_offline_form": "Display offline form",
"Displays_action_text": "Displays action text",
@ -638,6 +648,7 @@
"Hide_room": "Hide room",
"Hide_Room_Warning": "Are you sure you want to hide the room \"%s\"?",
"Hide_roles": "Hide roles",
"Hide_Unread_Room_Status": "Hide Unread Room Status",
"Hide_usernames": "Hide usernames",
"Highlights": "Highlights",
"Highlights_How_To": "To be notified when someone mentions a word or phrase, add it here. You can separate words or phrases with commas. Highlight Words are not case sensitive.",
@ -659,11 +670,11 @@
"Iframe_Integration_receive_enable": "Enable Receive",
"Iframe_Integration_receive_enable_Description": "Allow parent window to send commands to Rocket.Chat.",
"Iframe_Integration_receive_origin": "Receive origins",
"Iframe_Integration_receive_origin_Description": "Only pages with given origin will be able to send commands or `*` for all origins. You can use multiple values separated by `,`. Example `http://localhost,https://localhost`",
"Iframe_Integration_receive_origin_Description": "Origins with protocol prefix, separated by commas, which are allowed to receive commands e.g. 'https://localhost, http://localhost', or * to allow receiving from anywhere.",
"Iframe_Integration_send_enable": "Enable Send",
"Iframe_Integration_send_enable_Description": "Send events to parent window",
"Iframe_Integration_send_target_origin": "Send target origin",
"Iframe_Integration_send_target_origin_Description": "Only pages with given origin will be able to listen to events or `*` for all origins. Example `http://localhost`",
"Iframe_Integration_send_target_origin_Description": "Origin with protocol prefix, which commands are sent to e.g. 'https://localhost', or * to allow sending to anywhere.",
"Importer_Archived": "Archived",
"Importer_CSV_Information": "The CSV importer requires a specific format, please read the documentation for how to structure your zip file:",
"Importer_HipChatEnterprise_Information": "The file uploaded must be a decrypted tar.gz, please read the documentation for further information:",
@ -730,6 +741,8 @@
"Integration_Retry_Count_Description": "How many times should the integration be tried if the call to the url fails?",
"Integration_Retry_Delay": "Retry Delay",
"Integration_Retry_Delay_Description": "Which delay algorithm should the retrying use? <code class=\"inline\">10^x</code> or <code class=\"inline\">2^x</code> or <code class=\"inline\">x*2</code>",
"Integration_Run_When_Message_Is_Edited": "Run On Edits",
"Integration_Run_When_Message_Is_Edited_Description": "Should the integration run when the message is edited? Setting this to false will cause the integration to only run on <strong>new</strong> messages.",
"Integration_Word_Trigger_Placement": "Word Placement Anywhere",
"Integration_Word_Trigger_Placement_Description": "Should the Word be Triggered when placed anywhere in the sentence other than the beginning?",
"Integration_updated": "Integration has been updated.",
@ -968,9 +981,9 @@
"Message_AllowUnrecognizedSlashCommand": "Allow Unrecognized Slash Commands",
"Message_AlwaysSearchRegExp": "Always search using RegExp",
"Message_AlwaysSearchRegExp_Description": "We recommend to set `True` if your language is not supported on <a target=\"_blank\" href=\"https://docs.mongodb.org/manual/reference/text-search-languages/#text-search-languages\">MongoDB text search</a>.",
"Message_Attachments" : "Message Attachments",
"Message_Attachments_GroupAttach" : "Group Attachment Buttons",
"Message_Attachments_GroupAttachDescription" : "This groups the icons under an expandable menu. Takes up less screen space.",
"Message_Attachments": "Message Attachments",
"Message_Attachments_GroupAttach": "Group Attachment Buttons",
"Message_Attachments_GroupAttachDescription": "This groups the icons under an expandable menu. Takes up less screen space.",
"Message_AudioRecorderEnabled": "Audio Recorder Enabled",
"Message_AudioRecorderEnabledDescription": "Requires 'audio/wav' files to be an accepted media type within 'File Upload' settings.",
"Message_BadWordsFilterList": "Add bad words to the blacklist",
@ -1074,6 +1087,7 @@
"Nothing_found": "Nothing found",
"Notification_Duration": "Notification Duration",
"Notifications": "Notifications",
"Notifications_Muted_Description": "If you choose to mute everything, you won't see the room highlight in the list when there are new messages, except for mentions. Muting notifications will override notifications settings.",
"Notify_all_in_this_room": "Notify all in this room",
"Notify_active_in_this_room": "Notify active users in this room",
"Num_Agents": "# Agents",
@ -1112,6 +1126,7 @@
"or": "or",
"Open_your_authentication_app_and_enter_the_code": "Open your authentication app and enter the code. You can also use one of your backup codes.",
"Order": "Order",
"Or_talk_as_anonymous": "Or talk as anonymous",
"OS_Arch": "OS Arch",
"OS_Cpus": "OS CPU Count",
"OS_Freemem": "OS Free Memory",
@ -1350,6 +1365,7 @@
"Showing_archived_results": "<p>Showing <b>%s</b> archived results</p>",
"Showing_online_users": "Showing: <b>__total_showing__</b>, Online: __online__, Total: __total__ users",
"Showing_results": "<p>Showing <b>%s</b> results</p>",
"Sign_in_to_start_talking": "Sign in to start talking",
"since_creation": "since %s",
"Site_Name": "Site Name",
"Site_Url": "Site URL",
@ -1532,14 +1548,14 @@
"UI_DisplayRoles": "Display Roles",
"UI_Merge_Channels_Groups": "Merge private groups with channels",
"UI_Use_Name_Avatar": "Use full name initials to generate default avatar",
"UI_Use_Real_Name" : "Use Real Name",
"UI_Use_Real_Name": "Use Real Name",
"Unarchive": "Unarchive",
"Unblock_User": "Unblock User",
"Unmute_someone_in_room": "Unmute someone in the room",
"Unmute_user": "Unmute user",
"Unnamed": "Unnamed",
"Unpin_Message": "Unpin Message",
"Unread_Alert": "Unread Alert",
"Unread_Tray_Icon_Alert": "Unread Tray Icon Alert",
"Unread_Messages": "Unread Messages",
"Unread_Rooms": "Unread Rooms",
"Unread_Rooms_Mode": "Unread Rooms Mode",
@ -1703,4 +1719,4 @@
"your_message_optional": "your message (optional)",
"Your_password_is_wrong": "Your password is wrong!",
"Your_push_was_sent_to_s_devices": "Your push was sent to %s devices"
}
}

@ -578,6 +578,7 @@
"Importer_Prepare_Uncheck_Deleted_Users": "Los usuarios desmarque eliminados",
"Importer_progress_error": "No se pudo obtener el progreso de la importación.",
"Importer_setup_error": "Se produjo un error al configurar el importador.",
"Importer_Source_File": "Selección del archivo de origen",
"Incoming_Livechats": "LiveChats entrantes",
"inline_code": "inline_code",
"Install_Extension": "Instalar extension",
@ -588,9 +589,14 @@
"Installation": "Instalación ",
"Installed_at": "instalado en",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Instrucciones a sus visitantes llenan el formulario para enviar un mensaje",
"Integration_Advanced_Settings": "Ajustes Avanzados",
"Integration_added": "La Integración ha sido añadida",
"Integration_Incoming_WebHook": "Integración WebHook de Entrada",
"Integration_New": "Nueva Integración",
"Integrations_Outgoing_Type_FileUploaded": "Archivo Subido",
"Integrations_Outgoing_Type_RoomArchived": "chat archivado",
"Integrations_Outgoing_Type_RoomCreated": "chat creado(público y privado)",
"Integrations_Outgoing_Type_RoomJoined": "Usuario se ha unido al chat",
"Integration_Outgoing_WebHook": "Integración web hook saliente",
"Integration_updated": "La Integración ha sido actualizada",
"Integrations": "Integraciones",
@ -607,14 +613,18 @@
"Invalid_pass": "La contraseña no debe estar vacia",
"Invalid_room_name": "<strong>%s</strong> no es un nombre de sala válido,<br/> use solo letras, números y guiones",
"Invalid_secret_URL_message": "El URL proporcionado es invalido.",
"Invalid_setting_s": "Configuración no válida: %s",
"invisible": "invisible",
"Invisible": "Invisible",
"Invitation": "Invitación",
"Invitation_HTML": "HTML de la Invitación",
"Invitation_HTML_Default": "<h2> Se le ha invitado a <h1> [Site_Name] </h1></h2><p> Ir a [Site_URL] y probar la mejor solución de chat de código abierto disponibles en la actualidad! </p>",
"Invitation_HTML_Description": "Es posible utilizar los siguientes marcadores: <br/><ul><li> [email] para el correo electrónico del destinatario. </li><li> [Site_Name] y [Site_URL] para el nombre de la aplicación y la URL, respectivamente. </li></ul>",
"Invitation_Subject": "Asunto de la Invitación",
"Invitation_Subject_Default": "Se le ha invitado a [Site_Name]",
"Invite_user_to_join_channel": "Invitar a un usuario a unirse a este canal",
"Invite_user_to_join_channel_all_to": "Invitar a todos los usuarios de este canal a unirse a [#channel]",
"Invite_user_to_join_channel_all_from": "Invitar a todos los usuarios de [#channell] para unirse a este canal",
"Invite_Users": "Invitar Usuarios",
"is_also_typing": "también esta escribiendo",
"is_also_typing_female": "tambien esta escribiendo",
@ -622,6 +632,8 @@
"is_typing": "está escribiendo",
"is_typing_female": "esta escribiendo",
"is_typing_male": "esta escribiendo",
"IRC_Channel_Join": "Salida del comando JOIN",
"IRC_Channel_Leave": "Salida del comando PART",
"It_works": "Funciona",
"italics": "cursiva",
"Jitsi_Chrome_Extension": "Id extensión de Chrome",
@ -660,6 +672,7 @@
"Layout_Terms_of_Service": "Términos del Servicio",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
"LDAP_Connect_Timeout": "Tiempo de espera de conexión(ms)",
"LDAP_Custom_Domain_Search": "Dominio Personalizado de Busqueda",
"LDAP_Custom_Domain_Search_Description": "Un pedazo de JSON que gobierna se unen y la conexión y la información es de la forma: <br/> <code>{\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}</code>",
"LDAP_Default_Domain": "Dominio Predeterminado",
@ -1214,7 +1227,6 @@
"Unmute_user": "Des-silenciar usuario",
"Unnamed": "Sin nombre",
"Unpin_Message": "Desfijar Mensaje",
"Unread_Alert": "Alerta de no leídos",
"Unread_Rooms": "Salas sin leer",
"Unread_Rooms_Mode": "Modo Salas sin leer",
"Unstar_Message": "Eliminar Destacado",

File diff suppressed because it is too large Load Diff

@ -1097,7 +1097,6 @@
"Unmute_user": "בטל השתקת משתמש",
"Unnamed": "ללא שם",
"Unpin_Message": "שחרור הודעה",
"Unread_Alert": "התרעה על לא נקרא",
"Unread_Rooms": "חדרים שלא נקראו",
"Unread_Rooms_Mode": "מצב חדרים שלא נקראו",
"Unstar_Message": "הסר ממועדפים",

@ -1292,7 +1292,6 @@
"Unmute_user": "Uključi korisnika",
"Unnamed": "Neimenovano",
"Unpin_Message": "Otkvači Poruku",
"Unread_Alert": "Nepročitane obavijesti",
"Unread_Rooms": "Nepročitane Sobe",
"Unread_Rooms_Mode": "Mod Nepročitanih Soba",
"Unstar_Message": "Ukloni zvjezdicu",

@ -2,7 +2,7 @@
"#channel": "#canale",
"0_Errors_Only": "0 - Solo errori",
"1_Errors_and_Information": "1 - Errori e informazioni",
"2_Erros_Information_and_Debug": "2 - Errori, informazioni e di debug",
"2_Erros_Information_and_Debug": "2 - Errori, informazioni e debug",
"403": "Proibito",
"500": "Errore interno del server",
"@username": "@username",
@ -33,7 +33,7 @@
"Accounts_BlockedDomainsList_Description": "elenco separato da virgole dei domini bloccati",
"Accounts_BlockedUsernameList": "Lista nomi utente bloccati",
"Accounts_BlockedUsernameList_Description": "Lista di nomi utente bloccati, separati da virgole (ignora le maiuscole)",
"Accounts_CustomFields_Description": "Dovrebbe essere un JSON valido dove le chiavi sono i campi che contengono il dizionario delle impostazioni del campo. Esempio:<br/><code>{\n\"role\": {\n\"type\": \"select\",\n\"defaultValue\": \"student\",\n\"options\": [\"teacher\", \"student\"],\n\"required\": true,\n\"modifyRecordField\": {\n\"array\": true,\n\"field\": \"roles\"\n}\n},\n\"twitter\": {\n\"type\": \"text\",\n\"required\": true,\n\"minLength\": 2,\n\"maxLength\": 10\n}\n}</code> ",
"Accounts_CustomFields_Description": "Dovrebbe essere un JSON valido dove le chiavi sono i campi che contengono un dizionario di impostazioni. Esempio:<br/><code>{\n\"role\": {\n\"type\": \"select\",\n\"defaultValue\": \"student\",\n\"options\": [\"teacher\", \"student\"],\n\"required\": true,\n\"modifyRecordField\": {\n\"array\": true,\n\"field\": \"roles\"\n}\n},\n\"twitter\": {\n\"type\": \"text\",\n\"required\": true,\n\"minLength\": 2,\n\"maxLength\": 10\n}\n}</code> ",
"Accounts_denyUnverifiedEmail": "Blocca email non verificate",
"Accounts_EmailVerification": "Verifica email",
"Accounts_EmailVerification_Description": "Assicurati di aver impostato SMTP in modo corretto per utilizzare questa funzione",
@ -361,7 +361,7 @@
"Custom_Sound_Info": "Informazioni Suono Personalizzato",
"Custom_Sound_Saved_Successfully": "Suono personalizzato salvato con successo",
"Custom_Translations": "Traduzioni personalizzate",
"Custom_Translations_Description": "Dovrebbe essere un JSON valido dove le chiavi sono i campi che contengono il dizionario delle impostazioni del campo. Esempio:<br/><code>{\n\"en\": {\n\"Channels\": \"Rooms\"\n},\n\"pt\": {\n\"Channels\": \"Salas\"\n}\n}</code> ",
"Custom_Translations_Description": "Dovrebbe essere un JSON valido dove le chiavi sono le lingue che contengono un dizionario delle traduzioni. Esempio:<br/><code>{\n\"en\": {\n\"Channels\": \"Rooms\"\n},\n\"pt\": {\n\"Channels\": \"Salas\"\n}\n}</code> ",
"CustomSoundsFilesystem": "Filesystem suoni personalizzati",
"Dashboard": "Dashboard",
"Date": "Data",
@ -1045,7 +1045,7 @@
"Off_the_record_conversation": "Conversazione Off-the-record",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Conversazione Off-the-record non è disponibile per il browser o dispositivo.",
"Office_Hours": "Ore d'ufficio",
"Office_hours_enabled": "Ore d'ufficio attive",
"Office_hours_enabled": "Orario ufficio attivo",
"Offline": "Offline",
"Offline_DM_Email": "Hai ricevuto un messaggio diretto da __user__",
"Offline_form": "Modulo offline",
@ -1482,7 +1482,6 @@
"Unmute_user": "Togli il muto all'utente",
"Unnamed": "Senza nome",
"Unpin_Message": "Rimuovi il pin dal messaggio",
"Unread_Alert": "Avviso Non Letto",
"Unread_Rooms": "Stanze non letti",
"Unread_Rooms_Mode": "Modalità Stanze Non Letta",
"Unstar_Message": "Rimuovi segnalibro",

@ -1103,7 +1103,6 @@
"Unmute_user": "ミュートを解除",
"Unnamed": "無名",
"Unpin_Message": "ピン留めを外す",
"Unread_Alert": "未読アラート",
"Unread_Rooms": "未読のあるルーム",
"Unread_Rooms_Mode": "未読ルーム表示モード",
"Unstar_Message": "スターを外す",

@ -5,7 +5,7 @@
"2_Erros_Information_and_Debug": "2 - 오류, 정보 및 디버그",
"403": "금지됨",
"500": "내부 서버 오류",
"@username": "@username",
"@username": "@사용자명",
"@username_message": "@username <message>",
"__username__is_no_longer__role__defined_by__user_by_": "__ 사용자 이름 __는 __user_by__에 의해, __role__ 더 이상 없다",
"__username__was_set__role__by__user_by_": "__ 사용자 이름 __은 __user_by__에 의해 __role__ 설정했다",
@ -16,11 +16,11 @@
"Accessing_permissions": "권한 액세스",
"Account_SID": "계정 SID",
"Accounts": "계정",
"Accounts_AllowDeleteOwnAccount": "사용자가 자신의 계정을 삭제할 수있습니다.",
"Accounts_AllowedDomainsList": "허용 가능한 도메인 목록",
"Accounts_AllowDeleteOwnAccount": "사용자가 자신의 계정을 삭제할 수 있습니다.",
"Accounts_AllowedDomainsList": "허용 도메인 목록",
"Accounts_AllowedDomainsList_Description": "허용된 도메인을 쉼표(,)로 구분하기",
"Accounts_AllowEmailChange": "이메일 변경을 허용합니다",
"Accounts_AllowPasswordChange": "암호 변경 허용",
"Accounts_AllowPasswordChange": "암호 변경 허용합니다.",
"Accounts_AllowUserAvatarChange": "사용자 아바타 변경을 허용",
"Accounts_AllowUsernameChange": "사용자 이름 변경 허용",
"Accounts_AllowUserProfileChange": "사용자 프로필 변경을 허용",
@ -32,13 +32,15 @@
"Accounts_BlockedDomainsList_Description": "차단 된 도메인의 쉼표로 구분 된 목록",
"Accounts_BlockedUsernameList": "차단 된 사용자 이름 목록",
"Accounts_BlockedUsernameList_Description": "차단 된 사용자 이름의 쉼표로 구분 된 목록 (대소 문자 구분)",
"Accounts_CustomFields_Description": "키는 필드 세팅의 딕셔너리(dictionary) 를 포함하는 필드 이름들이어야 합니다.\n\n예:<br/><code>{\n\"role\": {\n\"type\": \"select\",\n\"defaultValue\": \"student\",\n\"options\": [\"teacher\", \"student\"],\n\"required\": true,\n\"modifyRecordField\": {\n\"array\": true,\n\"field\": \"roles\"\n}\n},\n\"twitter\": {\n\"type\": \"text\",\n\"required\": true,\n\"minLength\": 2,\n\"maxLength\": 10\n}\n}</code> ",
"Accounts_denyUnverifiedEmail": "확인되지 않은 이메일 거부",
"Accounts_EmailVerification": "이메일 확인",
"Accounts_EmailVerification_Description": "이 기능을 사용하려면 SMTP설정이 올바르게 되어있는지 확인해주십시오.",
"Accounts_Enrollment_Email": "등록된 이메일",
"Accounts_Enrollment_Email_Default": "<h2> 에 오신 것을 환영합니다 <h1> [Site_Name] </h1></h2><p> [Site_URL]로 이동하여 오늘날 최고의 오픈 소스 채팅 솔루션을보십시오! </p>",
"Accounts_Enrollment_Email_Description": "당신은 각각 사용자의 전체 이름, 이름 또는 성을 위해 [lname], [name], [fname]을 사용할 수 있습니다. <br /> 당신은 사용자의 이메일을 [email]을 사용할 수 있습니다.",
"Accounts_Enrollment_Email_Subject_Default": "에 오신 것을 환영합니다 [Site_Name]",
"Accounts_Enrollment_Email_Subject_Default": "[Site_Name] 에 오신 것을 환영합니다 ",
"Accounts_ForgetUserSessionOnWindowClose": "윈도루를 닫을 때에 사용자 설정을 삭제 합니다.",
"Accounts_Iframe_api_method": "API 메소드",
"Accounts_Iframe_api_url": "API URL",
"Accounts_iframe_enabled": "사용",
@ -53,9 +55,13 @@
"Accounts_OAuth_Custom_id": "Id",
"Accounts_OAuth_Custom_Identity_Path": "Identity 경로",
"Accounts_OAuth_Custom_Login_Style": "로그인 스타일",
"Accounts_OAuth_Custom_Merge_Users": "사용자 합치기",
"Accounts_OAuth_Custom_Scope": "범위",
"Accounts_OAuth_Custom_Secret": "비밀",
"Accounts_OAuth_Custom_Token_Path": "Token 경로",
"Accounts_OAuth_Custom_Token_Sent_Via": "토큰 보낸 비아",
"Accounts_OAuth_Custom_Username_Field": "사용자 이름 필드",
"Accounts_OAuth_Drupal": "Drupal Login 이 활성화 됨",
"Accounts_OAuth_Facebook": "Facebook 로그인",
"Accounts_OAuth_Facebook_callback_url": "페이스 북 콜백 URL",
"Accounts_OAuth_Facebook_id": "Facebook 앱 ID",
@ -93,6 +99,8 @@
"Accounts_OAuth_Wordpress_id": "WordPress ID",
"Accounts_OAuth_Wordpress_secret": "WordPress 암호",
"Accounts_PasswordReset": "암호 재설정",
"Accounts_OAuth_Proxy_host": "프록시 서버",
"Accounts_OAuth_Proxy_services": "프록시 서비스",
"Accounts_Registration_AuthenticationServices_Enabled": "인증 서비스에 등록",
"Accounts_RegistrationForm": "등록 양식",
"Accounts_RegistrationForm_Disabled": "비활성화",
@ -102,6 +110,7 @@
"Accounts_RegistrationForm_SecretURL": "등록 양식 비밀 URL",
"Accounts_RegistrationForm_SecretURL_Description": "당신은 당신의 등록 URL에 추가됩니다 임의의 문자열을 제공해야합니다. 예 : https://demo.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "회원 가입은 이름 필요",
"Accounts_SetDefaultAvatar": "기본 아바타 설정",
"Accounts_ShowFormLogin": "보기 양식 기반 로그인",
"Accounts_UseDefaultBlockedDomainsList": "기본값 사용 차단 된 도메인 목록",
"Accounts_UseDNSDomainCheck": "DNS 도메인 확인을 사용하여",
@ -113,6 +122,7 @@
"Add": "추가",
"Add_agent": "에이전트를 추가",
"Add_custom_oauth": "사용자 정의 OAuth 추가",
"Add_Domain": "도메인 추가",
"Add_manager": "관리자 추가",
"Add_user": "사용자 추가",
"Add_User": "사용자 추가",
@ -124,24 +134,33 @@
"Additional_Feedback": "추가 의견",
"Administration": "관리",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "OAuth2를 인증 한 후, 사용자는이 URL로 리디렉션됩니다",
"Agent": "에이전트",
"Agent_added": "에이전트는 추가",
"Agent_removed": "에이전트 제거",
"Alias": "별명",
"Alias_Format": "별칭 형식",
"Alias_Set": "별칭 설정",
"All": "모든",
"All_channels": "모든 채널",
"All_logs": "모든 로그",
"All_messages": "모든 메시지",
"Allow_Invalid_SelfSigned_Certs": "잘못된 Self-Signed Certs 허용",
"Allow_Invalid_SelfSigned_Certs_Description": "링크 확인 및 미리보기 무효 및 자체 서명 된 SSL 인증서의 허용.",
"Allow_switching_departments": "방문자가 부서를 변경할 수 있도록 허용함",
"Analytics_features_enabled": "기능 활성화",
"Analytics_features_messages_Description": "사용자가 메시지에 대해 수행 행동과 관련된 사용자 정의 이벤트를 추적합니다.",
"Analytics_features_rooms_Description": "채널 또는 그룹 (삭제두고 작성)에 대한 작업에 관련된 사용자 정의 이벤트를 추적합니다.",
"Analytics_features_users_Description": "사용자 (암호 재설정 시간, 프로필 사진 변경 등)에 관련 작업에 관련된 사용자 정의 이벤트를 추적합니다.",
"Analytics_Google": "구글 애널리틱스",
"and": "그리고",
"And_more": "그리고 더 __length __",
"Animals_and_Nature": "동물과 자연",
"Announcement": "공지",
"API": "API",
"API_Allow_Infinite_Count_Description": "REST API 호출이 모든 내용을 하나의 호출에 리턴 할 수 있도록 할까요?",
"API_Analytics": "분석",
"API_Drupal_URL": "Drupal 서버 URL",
"API_Drupal_URL_Description": "예: https://domain.com (마지막의 슬레시 제외)",
"API_Embed": "포함",
"API_EmbedDisabledFor": "사용자에대한 Embed 비활성화",
"API_EmbedDisabledFor_Description": "쉼표로 구분된 사용자 이름 목록",
@ -153,6 +172,7 @@
"API_GitHub_Enterprise_URL_Description": "예: http://domain.com (마지막 슬래시 제외)",
"API_Gitlab_URL": "GitLab URL",
"API_Token": "API 토큰",
"API_Upper_Count_Limit": "최대 레코드 수",
"API_User_Limit": "채널에 모든 사용자를 추가하는 사용자 제한",
"API_Wordpress_URL": "WordPress URL",
"Apiai_Key": "Api.ai 키",
@ -182,6 +202,10 @@
"AutoLinker_Urls_TLD": "AutoLinker TLD URL을",
"AutoLinker_Urls_www": "AutoLinker 'WWW'의 URL",
"AutoLinker_UrlsRegExp": "AutoLinker URL 정규 표현식",
"Automatic_Translation": "자동 번역",
"Auto_Translate": "자동 번역",
"AutoTranslate_Enabled": "자동 번역 활성화",
"AutoTranslate_GoogleAPIKey": "구글 API 키",
"Available": "유효한",
"Available_agents": "사용 가능한 에이전트",
"Avatar": "아바타 변경",
@ -199,9 +223,12 @@
"Back_to_integrations": "위로 통합에",
"Back_to_login": "로그인으로 돌아가기",
"Back_to_permissions": "돌아 가기 권한",
"Block_User": "사용자 차단",
"Body": "신체",
"bold": "굵게",
"BotHelpers_userFields": "사용자 필드",
"Branch": "분기",
"Bugsnag_api_key": "Bugsnag API 키",
"busy": "바쁨",
"Busy": "바쁨",
"busy_female": "바쁨",
@ -209,9 +236,14 @@
"busy_male": "바쁨",
"Busy_male": "바쁨",
"by": "으로",
"cache_cleared": "캐시가 삭제됨",
"Cancel": "취소",
"Cancel_message_input": "취소",
"Cannot_invite_users_to_direct_rooms": "객실을 지시하는 사용자를 초대 할 수 없습니다",
"CAS_autoclose": "로그인 팝업을 자동으로 닫음",
"CAS_button_color": "로그인 버튼 배경 색상",
"CAS_button_label_color": "로그인 버튼 텍스트 색상",
"CAS_button_label_text": "로그인 버튼 레이블",
"CDN_PREFIX": "CDN Prefix",
"Certificates_and_Keys": "인증서와 키",
"Changing_email": "변경 이메일",

@ -1202,7 +1202,6 @@
"Unmute_user": "Anuluj wyciszenie użytkownika",
"Unnamed": "Anonimowy",
"Unpin_Message": "Odepnij wiadomość",
"Unread_Alert": "Alarm nieprzeczytany",
"Unread_Rooms": "Nieprzeczytane pokoje",
"Unread_Rooms_Mode": "Tryb nieprzeczytanych pokoi",
"Unstar_Message": "Usuń oznaczenie",

@ -421,6 +421,7 @@
"Field": "Fält",
"Field_removed": "fältet avlägsnas",
"File_exceeds_allowed_size_of_bytes": "Filen överskrider tillåten storlek __size__ bytes",
"File_uploaded": "Uppladdad fil",
"FileUpload": "Uppladdad fil",
"FileUpload_Enabled": "Filuppladdningar aktiverade",
"FileUpload_File_Empty": "Tom fil",
@ -506,6 +507,7 @@
"Integration_added": "Integrationen har lagts",
"Integration_Incoming_WebHook": "Inkommande WebHook Integration",
"Integration_New": "Ny integrering",
"Integrations_Outgoing_Type_FileUploaded": "Uppladdad fil",
"Integration_Outgoing_WebHook": "Utgående WebHook Integration",
"Integration_updated": "Integrationen har uppdaterats",
"Integrations": "Integreringar",
@ -1103,6 +1105,8 @@
"Unread_Rooms": "Olästa rum",
"Unread_Rooms_Mode": "Olästa Rum Läge",
"Unstar_Message": "Ta bort stjärnmarkering",
"Upload_file_description": "Filbeskrivning",
"Upload_file_name": "Filnamn",
"Upload_file_question": "Ladda upp fil?",
"Uploading_file": "Laddar upp fil...",
"Uptime": "drifttid",

@ -1341,7 +1341,6 @@
"Unmute_user": "取消禁言",
"Unnamed": "未命名",
"Unpin_Message": "取消固定",
"Unread_Alert": "未读警报",
"Unread_Messages": "未读消息",
"Unread_Rooms": "未读房间",
"Unread_Rooms_Mode": "未读房间模式",

@ -122,9 +122,9 @@ Importer.CSV = class ImporterCSV extends Importer.Base {
super.updateRecord({ 'count.messages': messagesCount, 'messagesstatus': null });
super.addCountToTotal(messagesCount);
//Ensure we have some users, channels, and messages
if (tempUsers.length === 0 || tempChannels.length === 0 || messagesCount === 0) {
this.logger.warn(`The loaded users count ${ tempUsers.length }, the loaded channels ${ tempChannels.length }, and the loaded messages ${ messagesCount }`);
//Ensure we have at least a single user, channel, or message
if (tempUsers.length === 0 && tempChannels.length === 0 && messagesCount === 0) {
this.logger.error('No users, channels, or messages found in the import file.');
super.updateProgress(Importer.ProgressStep.ERROR);
return super.getProgress();
}

@ -118,7 +118,7 @@ Template.integrationsIncoming.helpers({
}
});
return `curl -X POST -H 'Content-Type: application/json' --data 'payload=${ JSON.stringify(data) }' ${ record.url }`;
return `curl -X POST -H 'Content-Type: application/json' --data '${ JSON.stringify(data) }' ${ record.url }`;
},
editorOptions() {

@ -225,6 +225,14 @@
<div class="settings-description">{{_ "Integration_Word_Trigger_Placement_Description"}}</div>
</div>
</div>
<div class="input-line double-col">
<label>{{_ "Integration_Run_When_Message_Is_Edited"}}</label>
<div>
<label><input type="radio" name="runOnEdits" value="1" checked="{{$eq data.runOnEdits true}}" /> {{_ "True"}}</label>
<label><input type="radio" name="runOnEdits" value="0" checked="{{$neq data.runOnEdits true}}" /> {{_ "False"}}</label>
<div class="settings-description">{{{_ "Integration_Run_When_Message_Is_Edited_Description"}}}</div>
</div>
</div>
{{/if}}
</div>
</div>

@ -9,7 +9,8 @@ Template.integrationsOutgoing.onCreated(function _integrationsOutgoingOnCreated(
token: Random.id(24),
retryFailedCalls: true,
retryCount: 6,
retryDelay: 'powers-of-ten'
retryDelay: 'powers-of-ten',
runOnEdits: true
});
this.updateRecord = () => {
@ -31,7 +32,8 @@ Template.integrationsOutgoing.onCreated(function _integrationsOutgoingOnCreated(
triggerWordAnywhere: $('[name=triggerWordAnywhere]').val() ? $('[name=triggerWordAnywhere]').val().trim() : undefined,
retryFailedCalls: $('[name=retryFailedCalls]:checked').val().trim() === '1',
retryCount: $('[name=retryCount]').val() ? $('[name=retryCount]').val().trim() : 6,
retryDelay: $('[name=retryDelay]').val() ? $('[name=retryDelay]').val().trim() : 'powers-of-ten'
retryDelay: $('[name=retryDelay]').val() ? $('[name=retryDelay]').val().trim() : 'powers-of-ten',
runOnEdits: $('[name=runOnEdits]:checked').val().trim() === '1'
});
};
@ -287,11 +289,13 @@ Template.integrationsOutgoing.events({
let triggerWords;
let triggerWordAnywhere;
let runOnEdits;
if (RocketChat.integrations.outgoingEvents[event].use.triggerWords) {
triggerWords = $('[name=triggerWords]').val().trim();
triggerWords = triggerWords.split(',').filter((word) => word.trim() !== '');
triggerWordAnywhere = $('[name=triggerWordAnywhere]').val().trim();
runOnEdits = $('[name=runOnEdits]:checked').val().trim();
}
let channel;
@ -338,7 +342,8 @@ Template.integrationsOutgoing.events({
retryFailedCalls: retryFailedCalls === '1',
retryCount: retryCount ? retryCount : 6,
retryDelay: retryDelay ? retryDelay : 'powers-of-ten',
triggerWordAnywhere: triggerWordAnywhere === '1'
triggerWordAnywhere: triggerWordAnywhere === '1',
runOnEdits: runOnEdits === '1'
};
const params = Template.instance().data.params? Template.instance().data.params() : undefined;

@ -10,6 +10,7 @@ function buildSandbox(store = {}) {
s,
console,
moment,
Livechat: RocketChat.Livechat,
Store: {
set(key, val) {
return store[key] = val;
@ -207,6 +208,12 @@ function executeIntegrationRest() {
return RocketChat.API.v1.failure(result.error);
}
this.bodyParams = result && result.content;
if (typeof result !== 'undefined') {
this.scriptResponse = result.response;
if (result.user) {
this.user = result.user;
}
}
logger.incoming.debug('[Process Incoming Request result of Trigger', this.integration.name, ':]');
logger.incoming.debug('result', this.bodyParams);
} catch ({stack}) {
@ -228,7 +235,10 @@ function executeIntegrationRest() {
if (_.isEmpty(message)) {
return RocketChat.API.v1.failure('unknown-error');
}
return RocketChat.API.v1.success();
if (this.scriptResponse) {
logger.incoming.debug('response', this.scriptResponse);
}
return RocketChat.API.v1.success(this.scriptResponse);
} catch ({error}) {
return RocketChat.API.v1.failure(error);
}

@ -389,6 +389,10 @@ RocketChat.integrations.triggerHandler = new class RocketChatIntegrationHandler
if (message.bot) {
data.bot = message.bot;
}
if (message.editedAt) {
data.isEdited = true;
}
break;
case 'fileUploaded':
data.channel_id = room._id;
@ -585,6 +589,11 @@ RocketChat.integrations.triggerHandler = new class RocketChatIntegrationHandler
}
}
if (message && message.editedAt && !trigger.runOnEdits) {
logger.outgoing.debug(`The trigger "${ trigger.name }"'s run on edits is disabled and the message was edited.`);
return;
}
const historyId = this.updateHistory({ step: 'start-execute-trigger-url', integration: trigger, event });
const data = {

@ -138,6 +138,11 @@ RocketChat.integrations.validateOutgoing = function _validateOutgoing(integratio
}
}
if (typeof integration.runOnEdits !== 'undefined') {
// Verify this value is only true/false
integration.runOnEdits = integration.runOnEdits === true;
}
_verifyUserHasPermissionForChannels(integration, userId, channels);
_verifyRetryInformation(integration);

@ -44,6 +44,7 @@ Meteor.methods({
retryCount: integration.retryCount,
retryDelay: integration.retryDelay,
triggerWordAnywhere: integration.triggerWordAnywhere,
runOnEdits: integration.runOnEdits,
_updatedAt: new Date(),
_updatedBy: RocketChat.models.Users.findOne(this.userId, {fields: {username: 1}})
}

@ -1,181 +0,0 @@
###
# KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.
# https://github.com/Khan/KaTeX
###
katex = require('katex')
class Katex
constructor: ->
@delimiters_map = [
{ opener: '\\[', closer: '\\]', displayMode: true , enabled: () => @parenthesis_syntax_enabled() },
{ opener: '\\(', closer: '\\)', displayMode: false, enabled: () => @parenthesis_syntax_enabled() },
{ opener: '$$' , closer: '$$' , displayMode: true , enabled: () => @dollar_syntax_enabled() },
{ opener: '$' , closer: '$' , displayMode: false, enabled: () => @dollar_syntax_enabled() },
]
# Searches for the first opening delimiter in the string from a given position
find_opening_delimiter: (str, start) -> # Search the string for each opening delimiter
matches = ({options: o, pos: str.indexOf(o.opener, start)} for o in @delimiters_map when o.enabled())
positions = (m.pos for m in matches when m.pos >= 0)
# No opening delimiters were found
if positions.length == 0
return null
# Take the first delimiter found
pos = Math.min.apply Math, positions
match_index = (m.pos for m in matches).indexOf(pos)
match = matches[match_index]
return match
class Boundary
length: ->
return @end - @start
extract: (str) ->
return str.substr @start, @length()
# Returns the outer and inner boundaries of the latex block starting
# at the given opening delimiter
get_latex_boundaries: (str, opening_delimiter_match) ->
inner = new Boundary
outer = new Boundary
# The closing delimiter matching to the opening one
closer = opening_delimiter_match.options.closer
outer.start = opening_delimiter_match.pos
inner.start = opening_delimiter_match.pos + closer.length
# Search for a closer delimiter after the opening one
closer_index = str.substr(inner.start).indexOf(closer)
if closer_index < 0
return null
inner.end = inner.start + closer_index
outer.end = inner.end + closer.length
return {
outer: outer
inner: inner
}
# Searches for the first latex block in the given string
find_latex: (str) ->
start = 0
while (opening_delimiter_match = @find_opening_delimiter str, start++)?
match = @get_latex_boundaries str, opening_delimiter_match
if match?.inner.extract(str).trim().length
match.options = opening_delimiter_match.options
return match
return null
# Breaks a message to what comes before, after and to the content of a
# matched latex block
extract_latex: (str, match) ->
before = str.substr 0, match.outer.start
after = str.substr match.outer.end
latex = match.inner.extract str
latex = s.unescapeHTML latex
return { before: before, latex : latex, after : after }
# Takes a latex math string and the desired display mode and renders it
# to HTML using the KaTeX library
render_latex: (latex, displayMode) ->
try
rendered = katex.renderToString latex , {displayMode: displayMode}
catch e
display_mode = if displayMode then "block" else "inline"
rendered = "<div class=\"katex-error katex-#{display_mode}-error\">"
rendered += "#{s.escapeHTML e.message}"
rendered += "</div>"
return rendered
# Takes a string and renders all latex blocks inside it
render: (str, render_func) ->
result = ''
loop
# Find the first latex block in the string
match = @find_latex str
unless match?
result += str
break
parts = @extract_latex str, match
# Add to the reuslt what comes before the latex block as well as
# the rendered latex content
rendered = render_func parts.latex, match.options.displayMode
result += parts.before + rendered
# Set what comes after the latex block to be examined next
str = parts.after
return result
# Takes a rocketchat message and renders latex in its content
render_message: (message) ->
# Render only if enabled in admin panel
if @katex_enabled()
msg = message
if not _.isString message
if _.trim message.html
msg = message.html
else
return message
if _.isString message
render_func = (latex, displayMode) =>
return @render_latex latex, displayMode
else
message.tokens ?= []
render_func = (latex, displayMode) =>
token = "=&=#{Random.id()}=&="
message.tokens.push
token: token
text: @render_latex latex, displayMode
return token
msg = @render msg, render_func
if not _.isString message
message.html = msg
else
message = msg
return message
katex_enabled: ->
return RocketChat.settings.get('Katex_Enabled')
dollar_syntax_enabled: ->
return RocketChat.settings.get('Katex_Dollar_Syntax')
parenthesis_syntax_enabled: ->
return RocketChat.settings.get('Katex_Parenthesis_Syntax')
RocketChat.katex = new Katex
cb = RocketChat.katex.render_message.bind(RocketChat.katex)
RocketChat.callbacks.add 'renderMessage', cb, RocketChat.callbacks.priority.HIGH - 1, 'katex'
if Meteor.isClient
Blaze.registerHelper 'RocketChatKatex', (text) ->
return RocketChat.katex.render_message text

@ -0,0 +1,255 @@
/*
* KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.
* https://github.com/Khan/KaTeX
*/
const katex = require('katex');
class Boundary {
constructor() {}
length() {
return this.end - this.start;
}
extract(str) {
return str.substr(this.start, this.length());
}
}
class Katex {
constructor() {
this.delimiters_map = [
{
opener: '\\[',
closer: '\\]',
displayMode: true,
enabled: () => {
return this.parenthesis_syntax_enabled();
}
}, {
opener: '\\(',
closer: '\\)',
displayMode: false,
enabled: () => {
return this.parenthesis_syntax_enabled();
}
}, {
opener: '$$',
closer: '$$',
displayMode: true,
enabled: () => {
return this.dollar_syntax_enabled();
}
}, {
opener: '$',
closer: '$',
displayMode: false,
enabled: () => {
return this.dollar_syntax_enabled();
}
}
];
}
// Searches for the first opening delimiter in the string from a given position
find_opening_delimiter(str, start) { // Search the string for each opening delimiter
const matches = (() => {
const map = this.delimiters_map;
const results = [];
map.forEach((op) => {
if (op.enabled()) {
results.push({
options: op,
pos: str.indexOf(op.opener, start)
});
}
});
return results;
})();
const positions = (() => {
const results = [];
matches.forEach((pos) => {
if (pos.pos >= 0) {
results.push(pos.pos);
}
});
return results;
})();
// No opening delimiters were found
if (positions.length === 0) {
return null;
}
//Take the first delimiter found
const pos = Math.min.apply(Math, positions);
const match_index = (()=> {
const results = [];
matches.forEach((m) => {
results.push(m.pos);
});
return results;
})().indexOf(pos);
const match = matches[match_index];
return match;
}
// Returns the outer and inner boundaries of the latex block starting
// at the given opening delimiter
get_latex_boundaries(str, opening_delimiter_match) {
const inner = new Boundary;
const outer = new Boundary;
// The closing delimiter matching to the opening one
const closer = opening_delimiter_match.options.closer;
outer.start = opening_delimiter_match.pos;
inner.start = opening_delimiter_match.pos + closer.length;
// Search for a closer delimiter after the opening one
const closer_index = str.substr(inner.start).indexOf(closer);
if (closer_index < 0) {
return null;
}
inner.end = inner.start + closer_index;
outer.end = inner.end + closer.length;
return {
outer,
inner
};
}
// Searches for the first latex block in the given string
find_latex(str) {
let start = 0;
let opening_delimiter_match;
while ((opening_delimiter_match = this.find_opening_delimiter(str, start++)) != null) {
const match = this.get_latex_boundaries(str, opening_delimiter_match);
if (match && match.inner.extract(str).trim().length) {
match.options = opening_delimiter_match.options;
return match;
}
}
return null;
}
// Breaks a message to what comes before, after and to the content of a
// matched latex block
extract_latex(str, match) {
const before = str.substr(0, match.outer.start);
const after = str.substr(match.outer.end);
let latex = match.inner.extract(str);
latex = s.unescapeHTML(latex);
return {
before,
latex,
after
};
}
// Takes a latex math string and the desired display mode and renders it
// to HTML using the KaTeX library
render_latex(latex, displayMode) {
let rendered;
try {
rendered = katex.renderToString(latex, {
displayMode
});
} catch (error) {
const e = error;
const display_mode = displayMode ? 'block' : 'inline';
rendered = `<div class="katex-error katex-${ display_mode }-error">`;
rendered += `${ s.escapeHTML(e.message) }`;
rendered += '</div>';
}
return rendered;
}
// Takes a string and renders all latex blocks inside it
render(str, render_func) {
let result = '';
while (this.find_latex(str) != null) {
// Find the first latex block in the string
const match = this.find_latex(str);
const parts = this.extract_latex(str, match);
// Add to the reuslt what comes before the latex block as well as
// the rendered latex content
const rendered = render_func(parts.latex, match.options.displayMode);
result += parts.before + rendered;
// Set what comes after the latex block to be examined next
str = parts.after;
}
return result += str;
}
// Takes a rocketchat message and renders latex in its content
render_message(message) {
//Render only if enabled in admin panel
let render_func;
if (this.katex_enabled()) {
let msg = message;
if (!_.isString(message)) {
if (_.trim(message.html)) {
msg = message.html;
} else {
return message;
}
}
if (_.isString(message)) {
render_func = (latex, displayMode) => {
return this.render_latex(latex, displayMode);
};
} else {
if (message.tokens == null) {
message.tokens = [];
}
render_func = (latex, displayMode) => {
const token = `=!=${ Random.id() }=!=`;
message.tokens.push({
token,
text: this.render_latex(latex, displayMode)
});
return token;
};
}
msg = this.render(msg, render_func);
if (!_.isString(message)) {
message.html = msg;
} else {
message = msg;
}
}
return message;
}
katex_enabled() {
return RocketChat.settings.get('Katex_Enabled');
}
dollar_syntax_enabled() {
return RocketChat.settings.get('Katex_Dollar_Syntax');
}
parenthesis_syntax_enabled() {
return RocketChat.settings.get('Katex_Parenthesis_Syntax');
}
}
RocketChat.katex = new Katex;
const cb = RocketChat.katex.render_message.bind(RocketChat.katex);
RocketChat.callbacks.add('renderMessage', cb, RocketChat.callbacks.priority.HIGH - 1, 'katex');
if (Meteor.isClient) {
Blaze.registerHelper('RocketChatKatex', function(text) {
return RocketChat.katex.render_message(text);
});
}

@ -6,15 +6,14 @@ Package.describe({
});
Package.onUse(function(api) {
api.use('coffeescript');
api.use('ecmascript');
api.use('underscore');
api.use('templating');
api.use('underscorestring:underscore.string');
api.use('rocketchat:lib');
api.addFiles('settings.coffee', 'server');
api.addFiles('katex.coffee');
api.addFiles('settings.js', 'server');
api.addFiles('katex.js');
api.addFiles('client/style.css', 'client');
const katexPath = 'node_modules/katex/dist/';

@ -1,6 +0,0 @@
Meteor.startup ->
enableQuery = {_id: 'Katex_Enabled', value: true}
RocketChat.settings.add 'Katex_Enabled', true, {type: 'boolean', group: 'Message', section: 'Katex', public: true, i18n: 'Katex_Enabled_Description'}
RocketChat.settings.add 'Katex_Parenthesis_Syntax', true, {type: 'boolean', group: 'Message', section: 'Katex', public: true, enableQuery, i18nDescription: 'Katex_Parenthesis_Syntax_Description'}
RocketChat.settings.add 'Katex_Dollar_Syntax', false, {type: 'boolean', group: 'Message', section: 'Katex', public: true, enableQuery, i18nDescription: 'Katex_Dollar_Syntax_Description'}

@ -0,0 +1,32 @@
Meteor.startup(function() {
const enableQuery = {
_id: 'Katex_Enabled',
value: true
};
RocketChat.settings.add('Katex_Enabled', true, {
type: 'boolean',
group: 'Message',
section: 'Katex',
'public': true,
i18n: 'Katex_Enabled_Description'
});
RocketChat.settings.add('Katex_Parenthesis_Syntax', true, {
type: 'boolean',
group: 'Message',
section: 'Katex',
'public': true,
enableQuery,
i18nDescription: 'Katex_Parenthesis_Syntax_Description'
});
return RocketChat.settings.add('Katex_Dollar_Syntax', false, {
type: 'boolean',
group: 'Message',
section: 'Katex',
'public': true,
enableQuery,
i18nDescription: 'Katex_Dollar_Syntax_Description'
});
});
// ---
// generated by coffee-script 1.9.2

@ -177,14 +177,12 @@ Meteor.startup(function() {
return chatMessages[Session.get('openedRoom')].confirmDeleteMsg(message);
},
validation(message) {
if (RocketChat.models.Subscriptions.findOne({
rid: message.rid
}) == null) {
if (RocketChat.models.Subscriptions.findOne({rid: message.rid}) == null) {
return false;
}
const hasPermission = RocketChat.authz.hasAtLeastOnePermission('delete-message', message.rid);
const isDeleteAllowed = RocketChat.settings.get('Message_AllowDeleting');
const deleteOwn = message.u && message.u_id === Meteor.userId();
const deleteOwn = message.u && message.u._id === Meteor.userId();
if (!(hasPermission || (isDeleteAllowed && deleteOwn))) {
return;
}

@ -165,7 +165,7 @@ class CachedCollection {
}
localforage.getItem(this.name, (error, data) => {
if (data && (data.version < this.version || data.token !== this.getToken())) {
if (data && (data.version < this.version || data.token !== this.getToken() || this.getToken() === undefined)) {
this.clearCache();
callback(false);
return;

@ -5,12 +5,13 @@ currentTracker = undefined
Meteor.defer ->
currentTracker = Tracker.autorun (c) ->
if RoomManager.open(type + name).ready() isnt true
BlazeLayout.render 'main', { modal: RocketChat.Layout.isEmbedded(), center: 'loading' }
user = Meteor.user()
if (user? and not user.username?) or (not user? and RocketChat.settings.get('Accounts_AllowAnonymousRead') is false)
BlazeLayout.render 'main'
return
user = Meteor.user()
unless user?.username
if RoomManager.open(type + name).ready() isnt true
BlazeLayout.render 'main', { modal: RocketChat.Layout.isEmbedded(), center: 'loading' }
return
currentTracker = undefined

@ -0,0 +1,98 @@
/* globals fireGlobalEvent readMessage currentTracker*/
currentTracker = undefined;
function openRoom(type, name) {
Session.set('openedRoom', null);
return Meteor.defer(() =>
currentTracker = Tracker.autorun(function(c) {
const user = Meteor.user();
if ((user && user.username == null) || user == null && RocketChat.settings.get('Accounts_AllowAnonymousAccess') === false) {
BlazeLayout.render('main');
return;
}
if (RoomManager.open(type + name).ready() !== true) {
BlazeLayout.render('main', { modal: RocketChat.Layout.isEmbedded(), center: 'loading' });
return;
}
if (currentTracker) {
currentTracker = undefined;
}
c.stop();
const room = RocketChat.roomTypes.findRoom(type, name, user);
if (room == null) {
if (type === 'd') {
Meteor.call('createDirectMessage', name, function(err) {
if (!err) {
RoomManager.close(type + name);
return openRoom('d', name);
} else {
Session.set('roomNotFound', {type, name});
BlazeLayout.render('main', {center: 'roomNotFound'});
return;
}
});
} else {
Meteor.call('getRoomByTypeAndName', type, name, function(err, record) {
if (err) {
Session.set('roomNotFound', {type, name});
return BlazeLayout.render('main', {center: 'roomNotFound'});
} else {
delete record.$loki;
RocketChat.models.Rooms.upsert({ _id: record._id }, _.omit(record, '_id'));
RoomManager.close(type + name);
return openRoom(type, name);
}
});
}
return;
}
const mainNode = document.querySelector('.main-content');
if (mainNode) {
for (const child of Array.from(mainNode.children)) {
if (child) { mainNode.removeChild(child); }
}
const roomDom = RoomManager.getDomOfRoom(type + name, room._id);
mainNode.appendChild(roomDom);
if (roomDom.classList.contains('room-container')) {
roomDom.querySelector('.messages-box > .wrapper').scrollTop = roomDom.oldScrollTop;
}
}
Session.set('openedRoom', room._id);
fireGlobalEvent('room-opened', _.omit(room, 'usernames'));
Session.set('editRoomTitle', false);
RoomManager.updateMentionsMarksOfRoom(type + name);
Meteor.setTimeout(() => readMessage.readNow(), 2000);
// KonchatNotification.removeRoomNotification(params._id)
if (Meteor.Device.isDesktop() && window.chatMessages && window.chatMessages[room._id] != null) {
setTimeout(() => $('.message-form .input-message').focus(), 100);
}
// update user's room subscription
const sub = ChatSubscription.findOne({rid: room._id});
if (sub && sub.open === false) {
Meteor.call('openRoom', room._id, function(err) {
if (err) {
return handleError(err);
}
});
}
if (FlowRouter.getQueryParam('msg')) {
const msg = { _id: FlowRouter.getQueryParam('msg'), rid: room._id };
RoomHistoryManager.getSurroundingMessages(msg);
}
return RocketChat.callbacks.run('enter-room', sub);
})
);
}
export { openRoom };
this.openRoom = openRoom;

@ -12,7 +12,7 @@ this.roomExit = function() {
if (mainNode == null) {
return;
}
return mainNode.children.forEach(child => {
return [...mainNode.children].forEach(child => {
if (child == null) {
return;
}

@ -1,87 +0,0 @@
RocketChat.roomTypes = new class roomTypesClient extends roomTypesCommon
checkCondition: (roomType) ->
return not roomType.condition? or roomType.condition()
getTypes: ->
orderedTypes = []
_.sortBy(@roomTypesOrder, 'order').forEach (type) =>
orderedTypes.push @roomTypes[type.identifier]
return orderedTypes
getIcon: (roomType) ->
return @roomTypes[roomType]?.icon
getRoomName: (roomType, roomData) ->
return @roomTypes[roomType]?.roomName roomData
getIdentifiers: (except) ->
except = [].concat except
list = _.reject @roomTypesOrder, (t) -> return except.indexOf(t.identifier) isnt -1
return _.map list, (t) -> return t.identifier
getUserStatus: (roomType, roomId) ->
return @roomTypes[roomType]?.getUserStatus?(roomId)
findRoom: (roomType, identifier, user) ->
return @roomTypes[roomType]?.findRoom identifier, user
canSendMessage: (roomId) ->
return ChatSubscription.find({ rid: roomId }).count() > 0
readOnly: (roomId, user) ->
fields = { ro: 1 }
# if a user has been specified then we want to see if that user has been muted in the room
if user
fields.muted = 1
room = ChatRoom.findOne({ _id: roomId }, fields : fields)
unless user
return room?.ro;
userOwner = RoomRoles.findOne({ rid: roomId, "u._id": user._id, roles: 'owner' }, { fields: { _id: 1 } })
return room?.ro is true and Array.isArray(room?.muted) and room?.muted.indexOf(user.username) != -1 and !userOwner
archived: (roomId) ->
fields = { archived: 1 }
room = ChatRoom.findOne({ _id: roomId }, fields : fields)
return room?.archived is true
verifyCanSendMessage: (roomId) ->
room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 } })
return if not room?.t?
roomType = room.t
return @roomTypes[roomType]?.canSendMessage roomId if @roomTypes[roomType]?.canSendMessage?
return @canSendMessage roomId
verifyShowJoinLink: (roomId) ->
room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 } })
return if not room?.t?
roomType = room.t
if not @roomTypes[roomType]?.showJoinLink?
return false
return @roomTypes[roomType].showJoinLink roomId
getNotSubscribedTpl: (roomId) ->
room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 } })
return if not room?.t?
roomType = room.t
if not @roomTypes[roomType]?.notSubscribedTpl?
return false
return @roomTypes[roomType].notSubscribedTpl

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save