commit
5c781693b9
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@ |
||||
export default new Mongo.Collection('autocompleteRecords'); |
||||
@ -1,25 +1,31 @@ |
||||
.message { |
||||
.actionLinks { |
||||
padding: 0; |
||||
& .actionLinks { |
||||
margin-top: 4px; |
||||
margin-bottom: 4px; |
||||
padding: 0; |
||||
|
||||
text-align: center; |
||||
|
||||
li { |
||||
cursor: pointer; |
||||
& li { |
||||
position: relative; |
||||
|
||||
display: inline; |
||||
|
||||
padding-right: 2px; |
||||
|
||||
list-style: none; |
||||
display: inline; |
||||
|
||||
.action-link { |
||||
cursor: pointer; |
||||
|
||||
& .action-link { |
||||
margin: 0 2px; |
||||
padding: 5px; |
||||
|
||||
border-radius: 7px; |
||||
margin: 0 2px; |
||||
} |
||||
} |
||||
|
||||
li:last-child::after { |
||||
& li:last-child::after { |
||||
content: none; |
||||
} |
||||
} |
||||
@ -1,51 +1,61 @@ |
||||
.permissions-manager { |
||||
h2 { |
||||
font-weight: bold !important; |
||||
font-size: 16px; |
||||
& h2 { |
||||
margin-top: 1em !important; |
||||
margin-bottom: 1em !important; |
||||
|
||||
border-bottom-width: 1px; |
||||
|
||||
font-size: 16px; |
||||
font-weight: bold !important; |
||||
} |
||||
|
||||
.permission-grid { |
||||
th { |
||||
white-space: normal; |
||||
text-align: center; |
||||
& .permission-grid { |
||||
& th { |
||||
position: relative; |
||||
|
||||
padding-top: 20px; |
||||
} |
||||
|
||||
td { |
||||
text-align: center; |
||||
white-space: normal; |
||||
} |
||||
|
||||
& td { |
||||
width: 10%; |
||||
|
||||
text-align: center; |
||||
} |
||||
|
||||
.icon-edit { |
||||
font-size: 80%; |
||||
& .icon-edit { |
||||
position: absolute; |
||||
padding-left: 2px; |
||||
top: 0; |
||||
left: 50%; |
||||
|
||||
padding-left: 2px; |
||||
|
||||
transform: translateX(-50%); |
||||
|
||||
font-size: 80%; |
||||
} |
||||
|
||||
.permission-name { |
||||
& .permission-name { |
||||
cursor: default; |
||||
} |
||||
} |
||||
|
||||
.empty-role { |
||||
& .empty-role { |
||||
padding: 0.5em !important; |
||||
} |
||||
|
||||
.form-role { |
||||
label { |
||||
width: 150px; |
||||
& .form-role { |
||||
& label { |
||||
display: inline-block; |
||||
|
||||
width: 150px; |
||||
|
||||
text-align: right; |
||||
} |
||||
|
||||
.form-buttons { |
||||
& .form-buttons { |
||||
padding-left: 150px; |
||||
} |
||||
} |
||||
@ -1,56 +1,63 @@ |
||||
.flex-tab { |
||||
.autotranslate { |
||||
ul { |
||||
li { |
||||
& .autotranslate { |
||||
& ul { |
||||
& li { |
||||
margin-bottom: 20px; |
||||
} |
||||
} |
||||
|
||||
form { |
||||
label { |
||||
& form { |
||||
& label { |
||||
display: block; |
||||
font-weight: bold; |
||||
|
||||
margin-bottom: 5px; |
||||
|
||||
font-weight: bold; |
||||
} |
||||
|
||||
div span { |
||||
& div span { |
||||
font-size: 14px; |
||||
|
||||
i.icon-pencil { |
||||
font-size: 12px; |
||||
& i.icon-pencil { |
||||
margin-left: 3px; |
||||
|
||||
font-size: 12px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.submit { |
||||
& .submit { |
||||
margin-top: 30px; |
||||
|
||||
text-align: center; |
||||
} |
||||
|
||||
[data-edit] { |
||||
& [data-edit] { |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.message { |
||||
.translated { |
||||
border-left: 1px dotted; |
||||
padding-left: 3px; |
||||
& .translated { |
||||
margin-left: 3px; |
||||
padding-left: 3px; |
||||
|
||||
border-left: 1px dotted; |
||||
|
||||
i.icon-language.loading { |
||||
& i.icon-language.loading { |
||||
display: inline-block; |
||||
|
||||
animation: spinh 2000ms infinite linear; |
||||
} |
||||
} |
||||
|
||||
&.sequential { |
||||
.translated { |
||||
border-left: 0; |
||||
& .translated { |
||||
position: absolute; |
||||
left: 5px; |
||||
|
||||
border-left: 0; |
||||
} |
||||
} |
||||
} |
||||
@ -1,97 +1,113 @@ |
||||
.flex-tab { |
||||
.channel-settings { |
||||
ul { |
||||
li { |
||||
& .channel-settings { |
||||
& ul { |
||||
& li { |
||||
margin-bottom: 20px; |
||||
} |
||||
} |
||||
|
||||
label { |
||||
& label { |
||||
display: block; |
||||
font-weight: bold; |
||||
|
||||
margin-bottom: 5px; |
||||
|
||||
font-size: 14px; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.current-setting { |
||||
font-size: 14px; |
||||
width: calc(~"100% - 38px"); |
||||
& .current-setting { |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
|
||||
width: calc(100% - 38px); |
||||
min-height: 20px; |
||||
cursor: pointer; |
||||
margin-top: 3px; |
||||
|
||||
cursor: pointer; |
||||
vertical-align: middle; |
||||
|
||||
font-size: 14px; |
||||
|
||||
&[data-edit="false"] { |
||||
cursor: inherit; |
||||
user-select: initial; |
||||
} |
||||
} |
||||
|
||||
.editing { |
||||
& .editing { |
||||
margin: -2px 0 -1px -9px; |
||||
padding-right: 80px; |
||||
|
||||
font-size: 14px; |
||||
margin: -2px 0 -1px -9px; |
||||
} |
||||
|
||||
.buttons { |
||||
& .buttons { |
||||
position: absolute; |
||||
top: -1px; |
||||
bottom: 0; |
||||
right: 10px; |
||||
bottom: 0; |
||||
|
||||
border-radius: 0 4px 4px 0; |
||||
|
||||
.button { |
||||
& .button { |
||||
padding: 8px; |
||||
} |
||||
} |
||||
|
||||
.button.edit { |
||||
padding: 8px; |
||||
font-size: 12px; |
||||
vertical-align: middle; |
||||
& .button.edit { |
||||
display: inline-block; |
||||
visibility: hidden; |
||||
|
||||
padding: 8px; |
||||
|
||||
vertical-align: middle; |
||||
|
||||
font-size: 12px; |
||||
} |
||||
|
||||
.submit { |
||||
& .submit { |
||||
margin-top: 30px; |
||||
|
||||
text-align: center; |
||||
} |
||||
|
||||
.boolean { |
||||
& .boolean { |
||||
font-size: 0; |
||||
|
||||
> label { |
||||
width: calc(~"100% - 45px"); |
||||
& > label { |
||||
display: inline-block; |
||||
|
||||
width: calc(100% - 45px); |
||||
|
||||
vertical-align: middle; |
||||
} |
||||
|
||||
.setting-block { |
||||
width: 40px; |
||||
& .setting-block { |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
|
||||
width: 40px; |
||||
margin-left: -5px; |
||||
|
||||
vertical-align: middle; |
||||
} |
||||
} |
||||
|
||||
.setting-block { |
||||
& .setting-block { |
||||
position: relative; |
||||
|
||||
font-size: 0; |
||||
|
||||
.loading-animation { |
||||
& .loading-animation { |
||||
top: 30px; |
||||
} |
||||
|
||||
&:hover { |
||||
.button.edit { |
||||
& .button.edit { |
||||
visibility: visible; |
||||
} |
||||
} |
||||
} |
||||
|
||||
nav { |
||||
& nav { |
||||
text-align: right; |
||||
} |
||||
} |
||||
@ -1,16 +1,20 @@ |
||||
.message-color { |
||||
display: inline-block; |
||||
|
||||
font-weight: 100; |
||||
} |
||||
|
||||
.message-color-sample { |
||||
position: relative; |
||||
top: 2px; |
||||
|
||||
display: inline-block; |
||||
|
||||
width: 14px; |
||||
height: 14px; |
||||
display: inline-block; |
||||
border-radius: 3px; |
||||
margin-right: 3px; |
||||
margin-left: 2px; |
||||
|
||||
border: 1px solid rgba(0, 0, 0, 0.2); |
||||
position: relative; |
||||
top: 2px; |
||||
border-radius: 3px; |
||||
} |
||||
@ -1,22 +1,27 @@ |
||||
.emoji { |
||||
image-rendering: auto; |
||||
font-size: inherit; |
||||
height: 22px; |
||||
width: 22px; |
||||
position: relative; |
||||
|
||||
display: inline-block; |
||||
overflow: hidden; |
||||
|
||||
width: 22px; |
||||
height: 22px; |
||||
margin: 0 0.15em; |
||||
line-height: normal; |
||||
|
||||
vertical-align: middle; |
||||
background-position: center; |
||||
white-space: nowrap; |
||||
text-indent: 100%; |
||||
|
||||
background-repeat: no-repeat; |
||||
background-position: center; |
||||
background-size: cover; |
||||
text-indent: 100%; |
||||
white-space: nowrap; |
||||
overflow: hidden; |
||||
|
||||
font-size: inherit; |
||||
line-height: normal; |
||||
image-rendering: auto; |
||||
} |
||||
|
||||
.emoji.big { |
||||
height: 44px !important; |
||||
width: 44px !important; |
||||
height: 44px !important; |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
/* globals Template chatMessages*/ |
||||
Template.messageBox.events({ |
||||
'click .emoji-picker-icon'(event) { |
||||
event.stopPropagation(); |
||||
event.preventDefault(); |
||||
if (RocketChat.EmojiPicker.isOpened()) { |
||||
RocketChat.EmojiPicker.close(); |
||||
} else { |
||||
RocketChat.EmojiPicker.open(event.currentTarget, (emoji) => { |
||||
const {input} = chatMessages[RocketChat.openedRoom]; |
||||
|
||||
const emojiValue = `:${ emoji }:`; |
||||
|
||||
const caretPos = input.selectionStart; |
||||
const textAreaTxt = input.value; |
||||
input.focus(); |
||||
if (document.execCommand) { |
||||
document.execCommand('insertText', false, emojiValue); |
||||
} else { |
||||
input.value = textAreaTxt.substring(0, caretPos) + emojiValue + textAreaTxt.substring(caretPos); |
||||
} |
||||
|
||||
input.focus(); |
||||
|
||||
input.selectionStart = caretPos + emojiValue.length; |
||||
input.selectionEnd = caretPos + emojiValue.length; |
||||
}); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
Template.messageBox.onCreated(function() { |
||||
RocketChat.EmojiPicker.init(); |
||||
}); |
||||
@ -1,29 +0,0 @@ |
||||
/* globals Template */ |
||||
Template.messageBox.events({ |
||||
'click .emoji-picker-icon'(event) { |
||||
event.stopPropagation(); |
||||
if (RocketChat.EmojiPicker.isOpened()) { |
||||
RocketChat.EmojiPicker.close(); |
||||
} else { |
||||
RocketChat.EmojiPicker.open(event.currentTarget, (emoji) => { |
||||
const input = $(event.currentTarget).parent().parent().find('.input-message'); |
||||
|
||||
const emojiValue = `:${ emoji }:`; |
||||
|
||||
const caretPos = input.prop('selectionStart'); |
||||
const textAreaTxt = input.val(); |
||||
|
||||
input.val(textAreaTxt.substring(0, caretPos) + emojiValue + textAreaTxt.substring(caretPos)); |
||||
|
||||
input.focus(); |
||||
|
||||
input.prop('selectionStart', caretPos + emojiValue.length); |
||||
input.prop('selectionEnd', caretPos + emojiValue.length); |
||||
}); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
Template.messageBox.onCreated(function() { |
||||
RocketChat.EmojiPicker.init(); |
||||
}); |
||||
@ -1,7 +1,9 @@ |
||||
.icon-github_enterprise::before { |
||||
height: 1em; |
||||
|
||||
content: ""; |
||||
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wJGBYxHYxl31wAAAHpSURBVDjLpZI/aFNRFMZ/973bJqGRPopV4qNq/+SpTYnWRhCKilShg9BGcHOM+GfQoZuLk4iLgw4qZNBaHLuIdBNHl7Ta1qdNFI3SihnaNG1MpH3vuiQYQnwZvHCG893zffc751z4z6PX5T5gA1DAKnAaOAQEgAfAVeCpl+CeCrlRuEC6maO4h0A1wl4tPAHMqNUthvrDdHYY7A3t4rDVjeO6rBU2FaABM1WCrBNoi48Mi+nH9yj+KtPibAKwJXfQ5vcRG7soUnYmWEuQgAEIYBv4cGpoILI0Z4tyYYPegS6UguyijZQ6J45GSNmZHzUcJYD2ii2Ajv7efZ8WZ6ZwXFj79hXpayW4O0SL1Nl/8jzZlZ9dQLFS70pgvZKIyGD0yvu5eRmMnrk1PjI81ir1qBACTdPevXj95mVuNX8XKDQc/+T334bZZ104cvzYw2s3J3qAL5WXSsDbf61NNMBu+wOBs+VSyQ84Nfhg028ZGx3/qyy0lC7lgi7lghBitoon03lvB8l0/k7Wnk+8mny0cyXzEcfZxgwfZPTyRMHsOzAFXE9YhtNQIJnOx4FpJXT1eSkn2g0frqMoFrfoCXcqlCOAGwnLuO/l4JymcWl5uRxzXUKghBAiZ5r+WaV4lrCM555zqO+x2d0ftGmpiA/0k70AAAAASUVORK5CYII=); |
||||
height: 1em; |
||||
background-position: center center; |
||||
background-repeat: no-repeat; |
||||
background-position: center center; |
||||
} |
||||
|
||||
@ -0,0 +1 @@ |
||||
node_modules |
||||
@ -0,0 +1,7 @@ |
||||
This directory and the files immediately inside it are automatically generated |
||||
when you change this package's NPM dependencies. Commit the files in this |
||||
directory (npm-shrinkwrap.json, .gitignore, and this README) to source control |
||||
so that others run the same versions of sub-dependencies. |
||||
|
||||
You should NOT check in the node_modules directory that Meteor automatically |
||||
creates; if you are using git, the .gitignore file tells git to ignore it. |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@ |
||||
For this to properly work, you need to have a Google Service Account; |
||||
https://console.cloud.google.com/apis/credentials |
||||
|
||||
Then you have to authorize that service account access to your buckets; |
||||
https://console.cloud.google.com/storage/browser |
||||
To do that, click on the ellipsis by your bucket's row and Edit object default permissions |
||||
Add user and paste the service account e-mail with owner privileges |
||||
@ -0,0 +1,84 @@ |
||||
RocketChat.GoogleVision = { |
||||
getVisionAttributes(attachment) { |
||||
const attributes = {}; |
||||
const labels = []; |
||||
if (attachment.labels && attachment.labels.length > 0) { |
||||
attachment.labels.forEach(label => { |
||||
labels.push({ label }); |
||||
}); |
||||
} |
||||
if (attachment.safeSearch && attachment.safeSearch && attachment.safeSearch.adult === true) { |
||||
labels.push({ label: 'NSFW', bgColor: 'red', fontColor: 'white' }); |
||||
} |
||||
if (attachment.safeSearch && attachment.safeSearch.violence === true) { |
||||
labels.push({ label: 'Violence', bgColor: 'red', fontColor: 'white' }); |
||||
} |
||||
if (attachment.colors && attachment.colors.length > 0) { |
||||
attributes.color = `#${ attachment.colors[0] }`; |
||||
} |
||||
if (attachment.logos && attachment.logos.length > 0) { |
||||
labels.push({ label: `Logo: ${ attachment.logos[0] }` }); |
||||
} |
||||
if (attachment.faces && attachment.faces.length > 0) { |
||||
let faceCount = 0; |
||||
attachment.faces.forEach(face => { |
||||
const faceAttributes = []; |
||||
if (face.joy) { |
||||
faceAttributes.push('Joy'); |
||||
} |
||||
if (face.sorrow) { |
||||
faceAttributes.push('Sorrow'); |
||||
} |
||||
if (face.anger) { |
||||
faceAttributes.push('Anger'); |
||||
} |
||||
if (face.surprise) { |
||||
faceAttributes.push('Surprise'); |
||||
} |
||||
if (faceAttributes.length > 0) { |
||||
labels.push({ label: `Face ${ ++faceCount }: ${ faceAttributes.join(', ') }` }); |
||||
} |
||||
}); |
||||
} |
||||
if (labels.length > 0) { |
||||
attributes.labels = labels; |
||||
} |
||||
return attributes; |
||||
}, |
||||
|
||||
init() { |
||||
Tracker.autorun(() => { |
||||
if (RocketChat.settings.get('GoogleVision_Enable')) { |
||||
RocketChat.callbacks.add('renderMessage', (message) => { |
||||
if (message.attachments && message.attachments.length > 0) { |
||||
for (const index in message.attachments) { |
||||
if (message.attachments.hasOwnProperty(index)) { |
||||
const attachment = message.attachments[index]; |
||||
message.attachments[index] = Object.assign(message.attachments[index], this.getVisionAttributes(attachment)); |
||||
} |
||||
} |
||||
} |
||||
return message; |
||||
}, RocketChat.callbacks.priority.HIGH - 3, 'googlevision'); |
||||
|
||||
RocketChat.callbacks.add('streamMessage', (message) => { |
||||
if (message.attachments && message.attachments.length > 0) { |
||||
for (const index in message.attachments) { |
||||
if (message.attachments.hasOwnProperty(index)) { |
||||
const attachment = message.attachments[index]; |
||||
message.attachments[index] = Object.assign(message.attachments[index], this.getVisionAttributes(attachment)); |
||||
} |
||||
} |
||||
} |
||||
}, RocketChat.callbacks.priority.HIGH - 3, 'googlevision-stream'); |
||||
} else { |
||||
RocketChat.callbacks.remove('renderMessage', 'googlevision'); |
||||
RocketChat.callbacks.remove('streamMessage', 'googlevision-stream'); |
||||
} |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
Meteor.startup(function() { |
||||
RocketChat.GoogleVision.init(); |
||||
}); |
||||
@ -0,0 +1,21 @@ |
||||
Package.describe({ |
||||
name: 'rocketchat:google-vision', |
||||
version: '0.0.1', |
||||
summary: 'Rocket.Chat Google Vision Integration', |
||||
git: '' |
||||
}); |
||||
|
||||
Npm.depends({ |
||||
'@google-cloud/storage': '1.2.1', |
||||
'@google-cloud/vision': '0.11.5' |
||||
}); |
||||
|
||||
Package.onUse(function(api) { |
||||
api.use([ |
||||
'ecmascript', |
||||
'rocketchat:lib' |
||||
]); |
||||
|
||||
api.addFiles('client/googlevision.js', 'client'); |
||||
api.addFiles(['server/settings.js', 'server/googlevision.js', 'server/models/Messages.js'], 'server'); |
||||
}); |
||||
@ -0,0 +1,153 @@ |
||||
class GoogleVision { |
||||
constructor() { |
||||
this.storage = Npm.require('@google-cloud/storage'); |
||||
this.vision = Npm.require('@google-cloud/vision'); |
||||
this.storageClient = {}; |
||||
this.visionClient = {}; |
||||
this.enabled = RocketChat.settings.get('GoogleVision_Enable'); |
||||
this.serviceAccount = {}; |
||||
RocketChat.settings.get('GoogleVision_Enable', (key, value) => { |
||||
this.enabled = value; |
||||
}); |
||||
RocketChat.settings.get('GoogleVision_ServiceAccount', (key, value) => { |
||||
try { |
||||
this.serviceAccount = JSON.parse(value); |
||||
this.storageClient = this.storage({ credentials: this.serviceAccount }); |
||||
this.visionClient = this.vision({ credentials: this.serviceAccount }); |
||||
} catch (e) { |
||||
this.serviceAccount = {}; |
||||
} |
||||
}); |
||||
RocketChat.settings.get('GoogleVision_Block_Adult_Images', (key, value) => { |
||||
if (value) { |
||||
RocketChat.callbacks.add('beforeSaveMessage', this.blockUnsafeImages.bind(this), RocketChat.callbacks.priority.MEDIUM, 'googlevision-blockunsafe'); |
||||
} else { |
||||
RocketChat.callbacks.remove('beforeSaveMessage', 'googlevision-blockunsafe'); |
||||
} |
||||
}); |
||||
RocketChat.callbacks.add('afterFileUpload', this.annotate.bind(this)); |
||||
} |
||||
|
||||
incCallCount(count) { |
||||
const currentMonth = new Date().getMonth(); |
||||
const maxMonthlyCalls = RocketChat.settings.get('GoogleVision_Max_Monthly_Calls') || 0; |
||||
if (maxMonthlyCalls > 0) { |
||||
if (RocketChat.settings.get('GoogleVision_Current_Month') !== currentMonth) { |
||||
RocketChat.settings.set('GoogleVision_Current_Month', currentMonth); |
||||
if (count > maxMonthlyCalls) { |
||||
return false; |
||||
} |
||||
} else if (count + (RocketChat.settings.get('GoogleVision_Current_Month_Calls') || 0) > maxMonthlyCalls) { |
||||
return false; |
||||
} |
||||
} |
||||
RocketChat.models.Settings.update({ _id: 'GoogleVision_Current_Month_Calls' }, { $inc: { value: count } }); |
||||
return true; |
||||
} |
||||
|
||||
blockUnsafeImages(message) { |
||||
if (this.enabled && this.serviceAccount && message && message.file && message.file._id) { |
||||
const file = RocketChat.models.Uploads.findOne({ _id: message.file._id }); |
||||
if (file && file.type && file.type.indexOf('image') !== -1 && file.store === 'GoogleCloudStorage:Uploads' && file.GoogleStorage) { |
||||
if (this.incCallCount(1)) { |
||||
const bucket = this.storageClient.bucket(RocketChat.settings.get('FileUpload_GoogleStorage_Bucket')); |
||||
const bucketFile = bucket.file(file.GoogleStorage.path); |
||||
const results = Meteor.wrapAsync(this.visionClient.detectSafeSearch, this.visionClient)(bucketFile); |
||||
if (results && results.adult === true) { |
||||
FileUpload.getStore('Uploads').deleteById(file._id); |
||||
const user = RocketChat.models.Users.findOneById(message.u && message.u._id); |
||||
if (user) { |
||||
RocketChat.Notifications.notifyUser(user._id, 'message', { |
||||
_id: Random.id(), |
||||
rid: message.rid, |
||||
ts: new Date, |
||||
msg: TAPi18n.__('Adult_images_are_not_allowed', {}, user.language) |
||||
}); |
||||
} |
||||
throw new Meteor.Error('GoogleVisionError: Image blocked'); |
||||
} |
||||
} else { |
||||
console.error('Google Vision: Usage limit exceeded'); |
||||
} |
||||
return message; |
||||
} |
||||
} |
||||
} |
||||
|
||||
annotate({ message }) { |
||||
const visionTypes = []; |
||||
if (RocketChat.settings.get('GoogleVision_Type_Document')) { |
||||
visionTypes.push('document'); |
||||
} |
||||
if (RocketChat.settings.get('GoogleVision_Type_Faces')) { |
||||
visionTypes.push('faces'); |
||||
} |
||||
if (RocketChat.settings.get('GoogleVision_Type_Landmarks')) { |
||||
visionTypes.push('landmarks'); |
||||
} |
||||
if (RocketChat.settings.get('GoogleVision_Type_Labels')) { |
||||
visionTypes.push('labels'); |
||||
} |
||||
if (RocketChat.settings.get('GoogleVision_Type_Logos')) { |
||||
visionTypes.push('logos'); |
||||
} |
||||
if (RocketChat.settings.get('GoogleVision_Type_Properties')) { |
||||
visionTypes.push('properties'); |
||||
} |
||||
if (RocketChat.settings.get('GoogleVision_Type_SafeSearch')) { |
||||
visionTypes.push('safeSearch'); |
||||
} |
||||
if (RocketChat.settings.get('GoogleVision_Type_Similar')) { |
||||
visionTypes.push('similar'); |
||||
} |
||||
if (this.enabled && this.serviceAccount && visionTypes.length > 0 && message.file && message.file._id) { |
||||
const file = RocketChat.models.Uploads.findOne({ _id: message.file._id }); |
||||
if (file && file.type && file.type.indexOf('image') !== -1 && file.store === 'GoogleCloudStorage:Uploads' && file.GoogleStorage) { |
||||
if (this.incCallCount(visionTypes.length)) { |
||||
const bucket = this.storageClient.bucket(RocketChat.settings.get('FileUpload_GoogleStorage_Bucket')); |
||||
const bucketFile = bucket.file(file.GoogleStorage.path); |
||||
this.visionClient.detect(bucketFile, visionTypes, Meteor.bindEnvironment((error, results) => { |
||||
if (!error) { |
||||
RocketChat.models.Messages.setGoogleVisionData(message._id, this.getAnnotations(visionTypes, results)); |
||||
} else { |
||||
console.trace('GoogleVision error: ', error.stack); |
||||
} |
||||
})); |
||||
} else { |
||||
console.error('Google Vision: Usage limit exceeded'); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
getAnnotations(visionTypes, visionData) { |
||||
if (visionTypes.length === 1) { |
||||
const _visionData = {}; |
||||
_visionData[`${ visionTypes[0] }`] = visionData; |
||||
visionData = _visionData; |
||||
} |
||||
const results = {}; |
||||
for (const index in visionData) { |
||||
if (visionData.hasOwnProperty(index)) { |
||||
switch (index) { |
||||
case 'faces': |
||||
case 'landmarks': |
||||
case 'labels': |
||||
case 'similar': |
||||
case 'logos': |
||||
results[index] = (results[index] || []).concat(visionData[index] || []); |
||||
break; |
||||
case 'safeSearch': |
||||
results['safeSearch'] = visionData['safeSearch']; |
||||
break; |
||||
case 'properties': |
||||
results['colors'] = visionData[index]['colors']; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
return results; |
||||
} |
||||
} |
||||
|
||||
RocketChat.GoogleVision = new GoogleVision; |
||||
@ -0,0 +1,10 @@ |
||||
RocketChat.models.Messages.setGoogleVisionData = function(messageId, visionData) { |
||||
const updateObj = {}; |
||||
for (const index in visionData) { |
||||
if (visionData.hasOwnProperty(index)) { |
||||
updateObj[`attachments.0.${ index }`] = visionData[index]; |
||||
} |
||||
} |
||||
|
||||
return this.update({ _id: messageId }, { $set: updateObj }); |
||||
}; |
||||
@ -0,0 +1,88 @@ |
||||
Meteor.startup(function() { |
||||
RocketChat.settings.add('GoogleVision_Enable', false, { |
||||
type: 'boolean', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
public: true, |
||||
enableQuery: { _id: 'FileUpload_Storage_Type', value: 'GoogleCloudStorage' } |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_ServiceAccount', '', { |
||||
type: 'string', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
multiline: true, |
||||
enableQuery: { _id: 'GoogleVision_Enable', value: true } |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Max_Monthly_Calls', 0, { |
||||
type: 'int', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
enableQuery: { _id: 'GoogleVision_Enable', value: true } |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Current_Month', 0, { |
||||
type: 'int', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
hidden: true |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Current_Month_Calls', 0, { |
||||
type: 'int', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
blocked: true |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Type_Document', false, { |
||||
type: 'boolean', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
enableQuery: { _id: 'GoogleVision_Enable', value: true } |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Type_Faces', false, { |
||||
type: 'boolean', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
enableQuery: { _id: 'GoogleVision_Enable', value: true } |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Type_Landmarks', false, { |
||||
type: 'boolean', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
enableQuery: { _id: 'GoogleVision_Enable', value: true } |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Type_Labels', false, { |
||||
type: 'boolean', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
enableQuery: { _id: 'GoogleVision_Enable', value: true } |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Type_Logos', false, { |
||||
type: 'boolean', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
enableQuery: { _id: 'GoogleVision_Enable', value: true } |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Type_Properties', false, { |
||||
type: 'boolean', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
enableQuery: { _id: 'GoogleVision_Enable', value: true } |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Type_SafeSearch', false, { |
||||
type: 'boolean', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
enableQuery: { _id: 'GoogleVision_Enable', value: true } |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Block_Adult_Images', false, { |
||||
type: 'boolean', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
enableQuery: [{ _id: 'GoogleVision_Enable', value: true }, { _id: 'GoogleVision_Type_SafeSearch', value: true }] |
||||
}); |
||||
RocketChat.settings.add('GoogleVision_Type_Similar', false, { |
||||
type: 'boolean', |
||||
group: 'FileUpload', |
||||
section: 'Google Vision', |
||||
enableQuery: { _id: 'GoogleVision_Enable', value: true } |
||||
}); |
||||
}); |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue