<commit_before>'use strict'

const Primus = require('primus')
const UglifyJS = require('uglify-js')
const fs = require('fs')
const path = require('path')
const util = require('util')
const BrowserFingerprint = require('browser_fingerprint')
const ActionHero = require('./../index.js')
const api = ActionHero.api

module.exports = class WebSocketServer extends ActionHero.Server {
  constructor () {
    super()
    this.type = 'websocket'

    this.attributes = {
      canChat: true,
      logConnections: true,
      logExits: true,
      sendWelcomeMessage: true,
      verbs: [
        'quit',
        'exit',
        'documentation',
        'roomAdd',
        'roomLeave',
        'roomView',
        'detailsView',
        'say'
      ]
    }
  }

  initialize () {
    this.fingerprinter = new BrowserFingerprint(api.config.servers.web.fingerprintOptions)
  }

  start () {
    const webserver = api.servers.servers.web
    this.server = new Primus(webserver.server, this.config.server)

    this.writeClientJS()

    this.server.on('connection', (rawConnection) => { this.handleConnection(rawConnection) })
    this.server.on('disconnection', (rawConnection) => { this.handleDisconnection(rawConnection) })

    this.log(`webSockets bound to ${webserver.options.bindIP}: ${webserver.options.port}`, 'debug')
    this.active = true

    this.on('connection', (connection) => {
      connection.rawConnection.on('data', (data) => { this.handleData(connection, data) })
    })

    this.on('actionComplete', (data) => {
      if (data.toRender !== false) {
        data.connection.response.messageCount = data.messageCount
        this.sendMessage(data.connection, data.response, data.messageCount)
      }
    })
  }

  stop () {
    this.active = false
    if (this.config.destroyClientsOnShutdown === true) {
      this.connections().forEach((connection) => { connection.destroy() })
    }

    this.server.destroy()
  }

  sendMessage (connection, message, messageCount) {
    if (message.error) {
      message.error = api.config.errors.serializers.servers.websocket(message.error)
    }

    if (!message.context) { message.context = 'response' }
    if (!messageCount) { messageCount = connection.messageCount }
    if (message.context === 'response' && !message.messageCount) { message.messageCount = messageCount }
    connection.rawConnection.write(message)
  }

  sendFile (connection, error, fileStream, mime, length, lastModified) {
    let content = ''
    let response = {
      error: error,
      content: null,
      mime: mime,
      length: length,
      lastModified: lastModified
    }

    try {
      if (!error) {
        fileStream.on('data', (d) => { content += d })
        fileStream.on('end', () => {
          response.content = content
          this.sendMessage(connection, response, connection.messageCount)
        })
      } else {
        this.sendMessage(connection, response, connection.messageCount)
      }
    } catch (e) {
      this.log(e, 'warning')
      this.sendMessage(connection, response, connection.messageCount)
    }
  }

  goodbye (connection) {
    connection.rawConnection.end()
  }

  compileActionheroWebsocketClientJS () {
    let ahClientSource = fs.readFileSync(path.join(__dirname, '/../client/ActionheroWebsocketClient.js')).toString()
    let url = this.config.clientUrl
    ahClientSource = ahClientSource.replace(/%%URL%%/g, url)
    let defaults = {}
    for (let i in this.config.client) { defaults[i] = this.config.client[i] }
    defaults.url = url
    let defaultsString = util.inspect(defaults)
    defaultsString = defaultsString.replace('\'window.location.origin\'', 'window.location.origin')
    ahClientSource = ahClientSource.replace('%%DEFAULTS%%', 'return ' + defaultsString)

    return ahClientSource
  }

  renderClientJS (minimize) {
    if (!minimize) { minimize = false }
    let libSource = api.servers.servers.websocket.server.library()
    let ahClientSource = this.compileActionheroWebsocketClientJS()
    ahClientSource =
      ';;;\r\n' +
      '(function(exports){ \r\n' +
      ahClientSource +
      '\r\n' +
      'exports.ActionheroWebsocketClient = ActionheroWebsocketClient; \r\n' +
      'exports.ActionheroWebsocketClient = ActionheroWebsocketClient; \r\n' +
      '})(typeof exports === \'undefined\' ? window : exports);'

    if (minimize) {
      return UglifyJS.minify(libSource + '\r\n\r\n\r\n' + ahClientSource).code
    } else {
      return (libSource + '\r\n\r\n\r\n' + ahClientSource)
    }
  }

  writeClientJS () {
    if (!api.config.general.paths['public'] || api.config.general.paths['public'].length === 0) {
      return
    }

    if (this.config.clientJsPath && this.config.clientJsName) {
      let clientJSPath = path.normalize(
        api.config.general.paths['public'][0] +
        path.sep +
        this.config.clientJsPath +
        path.sep
      )
      let clientJSName = this.config.clientJsName
      let clientJSFullPath = clientJSPath + clientJSName
      try {
        if (!fs.existsSync(clientJSPath)) {
          fs.mkdirSync(clientJSPath)
        }
        fs.writeFileSync(clientJSFullPath + '.js', this.renderClientJS(false))
        api.log(`wrote ${clientJSFullPath}.js`, 'debug')
        fs.writeFileSync(clientJSFullPath + '.min.js', this.renderClientJS(true))
        api.log(`wrote ${clientJSFullPath}.min.js`, 'debug')
      } catch (e) {
        api.log('Cannot write client-side JS for websocket server:', 'warning')
        api.log(e, 'warning')
        throw e
      }
    }
  }

  handleConnection (rawConnection) {
    const parsedCookies = this.fingerprinter.parseCookies(rawConnection)
    const fingerprint = parsedCookies[api.config.servers.web.fingerprintOptions.cookieKey]
    this.buildConnection({
      rawConnection: rawConnection,
      remoteAddress: rawConnection.address.ip,
      remotePort: rawConnection.address.port,
      fingerprint: fingerprint
    })
  }

  handleDisconnection (rawConnection) {
    const connections = this.connections()
    for (let i in connections) {
      if (connections[i] && rawConnection.id === connections[i].rawConnection.id) {
        connections[i].destroy()
        break
      }
    }
  }

  async handleData (connection, data) {
    const verb = data.event
    delete data.event
    connection.messageCount++
    connection.params = {}

    if (verb === 'action') {
      for (let v in data.params) {
        connection.params[v] = data.params[v]
      }
      connection.error = null
      connection.response = {}
      return this.processAction(connection)
    }

    if (verb === 'file') {
      connection.params = {
        file: data.file
      }
      return this.processFile(connection)
    }

    let words = []
    let message
    if (data.room) {
      words.push(data.room)
      delete data.room
    }
    for (let i in data) { words.push(data[i]) }
    try {
      let data = await connection.verbs(verb, words)
      message = {status: 'OK', context: 'response', data: data}
      return this.sendMessage(connection, message)
    } catch (error) {
      message = {status: error, context: 'response', data: data}
      return this.sendMessage(connection, message)
    }
  }
}
<commit_msg>conditionally close web socket server<commit_after>'use strict'

const Primus = require('primus')
const UglifyJS = require('uglify-js')
const fs = require('fs')
const path = require('path')
const util = require('util')
const BrowserFingerprint = require('browser_fingerprint')
const ActionHero = require('./../index.js')
const api = ActionHero.api

module.exports = class WebSocketServer extends ActionHero.Server {
  constructor () {
    super()
    this.type = 'websocket'

    this.attributes = {
      canChat: true,
      logConnections: true,
      logExits: true,
      sendWelcomeMessage: true,
      verbs: [
        'quit',
        'exit',
        'documentation',
        'roomAdd',
        'roomLeave',
        'roomView',
        'detailsView',
        'say'
      ]
    }
  }

  initialize () {
    this.fingerprinter = new BrowserFingerprint(api.config.servers.web.fingerprintOptions)
  }

  start () {
    const webserver = api.servers.servers.web
    this.server = new Primus(webserver.server, this.config.server)

    this.writeClientJS()

    this.server.on('connection', (rawConnection) => { this.handleConnection(rawConnection) })
    this.server.on('disconnection', (rawConnection) => { this.handleDisconnection(rawConnection) })

    this.log(`webSockets bound to ${webserver.options.bindIP}: ${webserver.options.port}`, 'debug')
    this.active = true

    this.on('connection', (connection) => {
      connection.rawConnection.on('data', (data) => { this.handleData(connection, data) })
    })

    this.on('actionComplete', (data) => {
      if (data.toRender !== false) {
        data.connection.response.messageCount = data.messageCount
        this.sendMessage(data.connection, data.response, data.messageCount)
      }
    })
  }

  stop () {
    this.active = false
    if (this.config.destroyClientsOnShutdown === true) {
      this.connections().forEach((connection) => { connection.destroy() })
    }

    if (this.server) { this.server.destroy() }
  }

  sendMessage (connection, message, messageCount) {
    if (message.error) {
      message.error = api.config.errors.serializers.servers.websocket(message.error)
    }

    if (!message.context) { message.context = 'response' }
    if (!messageCount) { messageCount = connection.messageCount }
    if (message.context === 'response' && !message.messageCount) { message.messageCount = messageCount }
    connection.rawConnection.write(message)
  }

  sendFile (connection, error, fileStream, mime, length, lastModified) {
    let content = ''
    let response = {
      error: error,
      content: null,
      mime: mime,
      length: length,
      lastModified: lastModified
    }

    try {
      if (!error) {
        fileStream.on('data', (d) => { content += d })
        fileStream.on('end', () => {
          response.content = content
          this.sendMessage(connection, response, connection.messageCount)
        })
      } else {
        this.sendMessage(connection, response, connection.messageCount)
      }
    } catch (e) {
      this.log(e, 'warning')
      this.sendMessage(connection, response, connection.messageCount)
    }
  }

  goodbye (connection) {
    connection.rawConnection.end()
  }

  compileActionheroWebsocketClientJS () {
    let ahClientSource = fs.readFileSync(path.join(__dirname, '/../client/ActionheroWebsocketClient.js')).toString()
    let url = this.config.clientUrl
    ahClientSource = ahClientSource.replace(/%%URL%%/g, url)
    let defaults = {}
    for (let i in this.config.client) { defaults[i] = this.config.client[i] }
    defaults.url = url
    let defaultsString = util.inspect(defaults)
    defaultsString = defaultsString.replace('\'window.location.origin\'', 'window.location.origin')
    ahClientSource = ahClientSource.replace('%%DEFAULTS%%', 'return ' + defaultsString)

    return ahClientSource
  }

  renderClientJS (minimize) {
    if (!minimize) { minimize = false }
    let libSource = api.servers.servers.websocket.server.library()
    let ahClientSource = this.compileActionheroWebsocketClientJS()
    ahClientSource =
      ';;;\r\n' +
      '(function(exports){ \r\n' +
      ahClientSource +
      '\r\n' +
      'exports.ActionheroWebsocketClient = ActionheroWebsocketClient; \r\n' +
      'exports.ActionheroWebsocketClient = ActionheroWebsocketClient; \r\n' +
      '})(typeof exports === \'undefined\' ? window : exports);'

    if (minimize) {
      return UglifyJS.minify(libSource + '\r\n\r\n\r\n' + ahClientSource).code
    } else {
      return (libSource + '\r\n\r\n\r\n' + ahClientSource)
    }
  }

  writeClientJS () {
    if (!api.config.general.paths['public'] || api.config.general.paths['public'].length === 0) {
      return
    }

    if (this.config.clientJsPath && this.config.clientJsName) {
      let clientJSPath = path.normalize(
        api.config.general.paths['public'][0] +
        path.sep +
        this.config.clientJsPath +
        path.sep
      )
      let clientJSName = this.config.clientJsName
      let clientJSFullPath = clientJSPath + clientJSName
      try {
        if (!fs.existsSync(clientJSPath)) {
          fs.mkdirSync(clientJSPath)
        }
        fs.writeFileSync(clientJSFullPath + '.js', this.renderClientJS(false))
        api.log(`wrote ${clientJSFullPath}.js`, 'debug')
        fs.writeFileSync(clientJSFullPath + '.min.js', this.renderClientJS(true))
        api.log(`wrote ${clientJSFullPath}.min.js`, 'debug')
      } catch (e) {
        api.log('Cannot write client-side JS for websocket server:', 'warning')
        api.log(e, 'warning')
        throw e
      }
    }
  }

  handleConnection (rawConnection) {
    const parsedCookies = this.fingerprinter.parseCookies(rawConnection)
    const fingerprint = parsedCookies[api.config.servers.web.fingerprintOptions.cookieKey]
    this.buildConnection({
      rawConnection: rawConnection,
      remoteAddress: rawConnection.address.ip,
      remotePort: rawConnection.address.port,
      fingerprint: fingerprint
    })
  }

  handleDisconnection (rawConnection) {
    const connections = this.connections()
    for (let i in connections) {
      if (connections[i] && rawConnection.id === connections[i].rawConnection.id) {
        connections[i].destroy()
        break
      }
    }
  }

  async handleData (connection, data) {
    const verb = data.event
    delete data.event
    connection.messageCount++
    connection.params = {}

    if (verb === 'action') {
      for (let v in data.params) {
        connection.params[v] = data.params[v]
      }
      connection.error = null
      connection.response = {}
      return this.processAction(connection)
    }

    if (verb === 'file') {
      connection.params = {
        file: data.file
      }
      return this.processFile(connection)
    }

    let words = []
    let message
    if (data.room) {
      words.push(data.room)
      delete data.room
    }
    for (let i in data) { words.push(data[i]) }
    try {
      let data = await connection.verbs(verb, words)
      message = {status: 'OK', context: 'response', data: data}
      return this.sendMessage(connection, message)
    } catch (error) {
      message = {status: error, context: 'response', data: data}
      return this.sendMessage(connection, message)
    }
  }
}
<|endoftext|>


<commit_before>/*
 *
 * * Copyright 2015 Acrolinx GmbH
 * *
 * * Licensed under the Apache License, Version 2.0 (the "License");
 * * you may not use this file except in compliance with the License.
 * * You may obtain a copy of the License at
 * *
 * * http://www.apache.org/licenses/LICENSE-2.0
 * *
 * * Unless required by applicable law or agreed to in writing, software
 * * distributed under the License is distributed on an "AS IS" BASIS,
 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * * See the License for the specific language governing permissions and
 * * limitations under the License.
 * *
 * * For more information visit: http://www.acrolinx.com
 *
 */

'use strict';
var AcrolinxPlugin = (function () {

    var clientComponents = [
        {
            id: 'com.acrolinx.sidebarexample',
            name: 'Acrolinx Sidebar Example Client',
            version: '1.2.3.999',
            category: 'MAIN'
        }
    ];

    function initAcrolinxSamplePlugin(config, editorAdapter) {
        var $sidebarContainer = $('#' + config.sidebarContainerId);
        var $sidebar = $('');
        $sidebarContainer.append($sidebar);
        var sidebarContentWindow = $sidebar.get(0).contentWindow;

        var adapter = editorAdapter;

        function onSidebarLoaded() {

            function initSidebarOnPremise() {
                sidebarContentWindow.acrolinxSidebar.init({
                    clientComponents: config.clientComponents || clientComponents,
                    clientSignature: config.clientSignature,
                    showServerSelector: config.hasOwnProperty("showServerSelector") ? config.showServerSelector : true,
                    enableSingleSignOn: config.hasOwnProperty("enableSingleSignOn") ? config.enableSingleSignOn : false,
                    serverAddress: config.serverAddress

                    // These settings are only effective on servers with disabled checking profiles.
                    //checkSettings: {
                    //  'language': 'en',
                    //  'ruleSetName': 'Plain English',
                    //  'termSets': ['Medical'],
                    //  'checkSpelling': true,
                    //  'checkGrammar': true,
                    //  'checkStyle': true,
                    //  'checkReuse': false,
                    //  'harvestTerms': false,
                    //  'checkSeo': false,
                    //  'termStatuses': ['TERMINOLOGY_DEPRECATED']
                    //}

                    // These settings are only effective on servers with disabled checking profiles.
                    //defaultCheckSettings: {
                    //  'language': 'en',
                    //  'ruleSetName': 'Plain English',
                    //  'termSets': ['Medical'],
                    //  'checkSpelling': true,
                    //  'checkGrammar': true,
                    //  'checkStyle': true,
                    //  'checkReuse': false,
                    //  'harvestTerms': false,
                    //  'checkSeo': false,
                    //  'termStatuses': ['TERMINOLOGY_DEPRECATED']
                    //}

                });
            }

            console.log('Install acrolinxPlugin in sidebar.');
            sidebarContentWindow.acrolinxPlugin = {

                requestInit: function () {
                    console.log('requestInit');
                        initSidebarOnPremise();
                },

                onInitFinished: function (initFinishedResult) {
                    console.log('onInitFinished: ', initFinishedResult);
                    if (initFinishedResult.error) {
                        window.alert(initFinishedResult.error.message);
                    }
                },

                configure: function (configuration) {
                    console.log('configure: ', configuration);
                },

                requestGlobalCheckSync: function (html, format, documentReference) {
                    if (html.hasOwnProperty("error")) {
                        window.alert(html.error);
                    } else {
                        var checkInfo = sidebarContentWindow.acrolinxSidebar.checkGlobal(html.html, {
                            inputFormat: format || 'HTML',
                            requestDescription: {
                                documentReference: documentReference || 'filename.html'
                            }
                        });
                        adapter.registerCheckCall(checkInfo);
                    }

                },

                requestGlobalCheck: function () {
                    console.log('requestGlobalCheck');
                    var pHtml = adapter.extractHTMLForCheck();
                    var pFormat = adapter.getFormat ? adapter.getFormat() : null;
                    var pDocumentReference = adapter.getDocumentReference ? adapter.getDocumentReference() : null;
                    if (pHtml.then !== undefined) {
                        var self = this;
                        pHtml.then(function (html) {
                            self.requestGlobalCheckSync(html, pFormat, pDocumentReference);
                        });
                    } else {
                        this.requestGlobalCheckSync(pHtml, pFormat, pDocumentReference);

                    }
                },

                onCheckResult: function (checkResult) {
                    return adapter.registerCheckResult(checkResult);
                },

                selectRanges: function (checkId, matches) {
                    console.log('selectRanges: ', checkId, matches);
                    adapter.selectRanges(checkId, matches);

                },

                replaceRanges: function (checkId, matchesWithReplacement) {
                    console.log('replaceRanges: ', checkId, matchesWithReplacement);
                    adapter.replaceRanges(checkId, matchesWithReplacement);

                },

                // only needed for local checks
                getRangesOrder: function (checkedDocumentRanges) {
                    console.log('getRangesOrder: ', checkedDocumentRanges);
                    return [];
                },

                download: function (download) {
                    console.log('download: ', download.url, download);
                    window.open(download.url);
                },

                // only needed for local checks
                verifyRanges: function (checkedDocumentParts) {
                    console.log('verifyRanges: ', checkedDocumentParts);
                    return [];
                },

                disposeCheck: function (checkId) {
                    console.log('disposeCheck: ', checkId);
                }
            };

        }

        function loadSidebarIntoIFrame() {
            var sidebarBaseUrl;
            if (config.sidebarUrl !== undefined) {
                sidebarBaseUrl = config.sidebarUrl;
            } else {
                sidebarBaseUrl = 'https://acrolinx-sidebar-classic.s3.amazonaws.com/v14/prod/';
            }
            return $.ajax({
                url: sidebarBaseUrl + 'index.html'
            }).then(function (sidebarHtml) {
                var sidebarHtmlWithAbsoluteLinks = sidebarHtml
                    .replace(/src="/g, 'src="' + sidebarBaseUrl)
                    .replace(/href="/g, 'href="' + sidebarBaseUrl);
                sidebarContentWindow.document.open();
                sidebarContentWindow.document.write(sidebarHtmlWithAbsoluteLinks);
                sidebarContentWindow.document.close();
                onSidebarLoaded();
            });
        }

        loadSidebarIntoIFrame();
    }

    var cls = function (conf) {
        this.config = conf;
    };

    cls.prototype = {

        registerAdapter: function (adapter) {
            this.adapter = adapter;
        },

        init: function () {
            initAcrolinxSamplePlugin(this.config, this.adapter);
        }
    };

    return cls;

})();<commit_msg>added possibility to set default check settings from outside<commit_after>/*
 *
 * * Copyright 2015 Acrolinx GmbH
 * *
 * * Licensed under the Apache License, Version 2.0 (the "License");
 * * you may not use this file except in compliance with the License.
 * * You may obtain a copy of the License at
 * *
 * * http://www.apache.org/licenses/LICENSE-2.0
 * *
 * * Unless required by applicable law or agreed to in writing, software
 * * distributed under the License is distributed on an "AS IS" BASIS,
 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * * See the License for the specific language governing permissions and
 * * limitations under the License.
 * *
 * * For more information visit: http://www.acrolinx.com
 *
 */

'use strict';
var AcrolinxPlugin = (function () {

    var clientComponents = [
        {
            id: 'com.acrolinx.sidebarexample',
            name: 'Acrolinx Sidebar Example Client',
            version: '1.2.3.999',
            category: 'MAIN'
        }
    ];

    function initAcrolinxSamplePlugin(config, editorAdapter) {
        var $sidebarContainer = $('#' + config.sidebarContainerId);
        var $sidebar = $('');
        $sidebarContainer.append($sidebar);
        var sidebarContentWindow = $sidebar.get(0).contentWindow;

        var adapter = editorAdapter;

        function onSidebarLoaded() {

            function initSidebarOnPremise() {
                sidebarContentWindow.acrolinxSidebar.init({
                    clientComponents: config.clientComponents || clientComponents,
                    clientSignature: config.clientSignature,
                    showServerSelector: config.hasOwnProperty("showServerSelector") ? config.showServerSelector : true,
                    enableSingleSignOn: config.hasOwnProperty("enableSingleSignOn") ? config.enableSingleSignOn : false,
                    serverAddress: config.serverAddress,
                    defaultCheckSettings: config.defaultCheckSettings

                    // These settings are only effective on servers with disabled checking profiles.
                    //checkSettings: {
                    //  'language': 'en',
                    //  'ruleSetName': 'Plain English',
                    //  'termSets': ['Medical'],
                    //  'checkSpelling': true,
                    //  'checkGrammar': true,
                    //  'checkStyle': true,
                    //  'checkReuse': false,
                    //  'harvestTerms': false,
                    //  'checkSeo': false,
                    //  'termStatuses': ['TERMINOLOGY_DEPRECATED']
                    //}

                    // These settings are only effective on servers with disabled checking profiles.
                    //defaultCheckSettings: {
                    //  'language': 'en',
                    //  'ruleSetName': 'Plain English',
                    //  'termSets': ['Medical'],
                    //  'checkSpelling': true,
                    //  'checkGrammar': true,
                    //  'checkStyle': true,
                    //  'checkReuse': false,
                    //  'harvestTerms': false,
                    //  'checkSeo': false,
                    //  'termStatuses': ['TERMINOLOGY_DEPRECATED']
                    //}

                });
            }

            console.log('Install acrolinxPlugin in sidebar.');
            sidebarContentWindow.acrolinxPlugin = {

                requestInit: function () {
                    console.log('requestInit');
                        initSidebarOnPremise();
                },

                onInitFinished: function (initFinishedResult) {
                    console.log('onInitFinished: ', initFinishedResult);
                    if (initFinishedResult.error) {
                        window.alert(initFinishedResult.error.message);
                    }
                },

                configure: function (configuration) {
                    console.log('configure: ', configuration);
                },

                requestGlobalCheckSync: function (html, format, documentReference) {
                    if (html.hasOwnProperty("error")) {
                        window.alert(html.error);
                    } else {
                        var checkInfo = sidebarContentWindow.acrolinxSidebar.checkGlobal(html.html, {
                            inputFormat: format || 'HTML',
                            requestDescription: {
                                documentReference: documentReference || 'filename.html'
                            }
                        });
                        adapter.registerCheckCall(checkInfo);
                    }

                },

                requestGlobalCheck: function () {
                    console.log('requestGlobalCheck');
                    var pHtml = adapter.extractHTMLForCheck();
                    var pFormat = adapter.getFormat ? adapter.getFormat() : null;
                    var pDocumentReference = adapter.getDocumentReference ? adapter.getDocumentReference() : null;
                    if (pHtml.then !== undefined) {
                        var self = this;
                        pHtml.then(function (html) {
                            self.requestGlobalCheckSync(html, pFormat, pDocumentReference);
                        });
                    } else {
                        this.requestGlobalCheckSync(pHtml, pFormat, pDocumentReference);

                    }
                },

                onCheckResult: function (checkResult) {
                    return adapter.registerCheckResult(checkResult);
                },

                selectRanges: function (checkId, matches) {
                    console.log('selectRanges: ', checkId, matches);
                    adapter.selectRanges(checkId, matches);

                },

                replaceRanges: function (checkId, matchesWithReplacement) {
                    console.log('replaceRanges: ', checkId, matchesWithReplacement);
                    adapter.replaceRanges(checkId, matchesWithReplacement);

                },

                // only needed for local checks
                getRangesOrder: function (checkedDocumentRanges) {
                    console.log('getRangesOrder: ', checkedDocumentRanges);
                    return [];
                },

                download: function (download) {
                    console.log('download: ', download.url, download);
                    window.open(download.url);
                },

                // only needed for local checks
                verifyRanges: function (checkedDocumentParts) {
                    console.log('verifyRanges: ', checkedDocumentParts);
                    return [];
                },

                disposeCheck: function (checkId) {
                    console.log('disposeCheck: ', checkId);
                }
            };

        }

        function loadSidebarIntoIFrame() {
            var sidebarBaseUrl;
            if (config.sidebarUrl !== undefined) {
                sidebarBaseUrl = config.sidebarUrl;
            } else {
                sidebarBaseUrl = 'https://acrolinx-sidebar-classic.s3.amazonaws.com/v14/prod/';
            }
            return $.ajax({
                url: sidebarBaseUrl + 'index.html'
            }).then(function (sidebarHtml) {
                var sidebarHtmlWithAbsoluteLinks = sidebarHtml
                    .replace(/src="/g, 'src="' + sidebarBaseUrl)
                    .replace(/href="/g, 'href="' + sidebarBaseUrl);
                sidebarContentWindow.document.open();
                sidebarContentWindow.document.write(sidebarHtmlWithAbsoluteLinks);
                sidebarContentWindow.document.close();
                onSidebarLoaded();
            });
        }

        loadSidebarIntoIFrame();
    }

    var cls = function (conf) {
        this.config = conf;
    };

    cls.prototype = {

        registerAdapter: function (adapter) {
            this.adapter = adapter;
        },

        init: function () {
            initAcrolinxSamplePlugin(this.config, this.adapter);
        }
    };

    return cls;

})();<|endoftext|>


<commit_before>module.exports.name = 'raidban';

module.exports.alias = ['banraid', 'raidban'];

module.exports.isAllowed = (message) => {
  return (
    message.member.hasPermission('BAN_MEMBERS') ||
    message.member.roles.cache.has('543721608506900480')
  );
};

module.exports.help =
  ' `,raidban <user or timestamp Discord ID> [--end user or timestamp Discord ID] [--except user-mentions]`\n Ban all the users joined after the mentioned guy. Can also specify the last guy with `--end`. ALL INCLUSIVE. \nExamples:\n`,raidban @NewGuy`\n`,raidban @FirstGuy --end @LastGuy --except @InnocentGuy` will ban @FirstGuy and anyone after that up to and including @LastGuy, except @InnocentGuy';

const Discord = require('discord.js');

module.exports.command = async (message, content, bot, server) => {
  const badPeople = [];
  const executor = message.author;
  let deleteDays = 1;
  const reason = 'Mass Ban';
  let endID = null;
  const endFlag = content.match(/--end\s+([0-9]{17,21})/);
  if (endFlag) {
    content = content.replace(/--end\s+[0-9]{17,21}/, '');
    endID = endFlag[1];
  }
  let [first, exceptions] = content.split('--except');
  const exceptionIDs = exceptions ? exceptions.match(/[0-9]{17,21}/g) : [];
  const firstMatch = first ? first.match(/[0-9]{17,21}/) : null;
  const firstID = firstMatch && firstMatch[0];

  if (!firstID) {
    message.channel.send('Failed to resolve the first user');
    return;
  }
  const firstMem = server.guild.member(firstID);
  let firstMillis;
  if (firstMem && firstMem.joinedAt) {
    firstMillis = firstMem.joinedAt.getTime();
  } else {
    const date = Discord.SnowflakeUtil.deconstruct(firstID).date;
    firstMillis = date.getTime();
  }
  const endMem = endID ? server.guild.member(endID) : null;

  const nowMillis = new Date().getTime();
  if (nowMillis - firstMillis > 86400000) {
    message.channel.send('The first user join date cannot be older than 1 day');
    return;
  }
  let endMillis = nowMillis;
  if (endMem && endMem.joinedAt) {
    endMillis = endMem.joinedAt.getTime();
  } else if (endID) {
    const date = Discord.SnowflakeUtil.deconstruct(endID).date;
    endMillis = date.getTime();
  }
  if (endMillis - firstMillis < 0) {
    message.channel.send('The last guy joined before the first guy');
    return;
  }

  server.guild.members.cache.forEach((mem, memID) => {
    if (!mem.joinedAt) return;
    const memMillis = mem.joinedAt.getTime();
    if (
      memMillis >= firstMillis &&
      memMillis <= endMillis &&
      !exceptionIDs.includes(memID)
    ) {
      badPeople.push(mem);
    }
  });

  if (badPeople.length === 0) {
    message.channel.send('Failed to get members...');
    return;
  }

  const banMessage = `<:hypergeralthinkban:443803651325034507>  **You are banning ${
    badPeople.length
  } people!**  <:hypergeralthinkban:443803651325034507>\n\n${badPeople
    .map((m) => m.toString())
    .join('\n')}\n\nType \`confirm\` or \`cancel\``;
  await message.channel.send(banMessage, { split: true });
  const filter = (m) => m.member.id == executor.id;
  const collector = message.channel.createMessageCollector(filter, {
    time: 45000,
  });
  collector.on('collect', (m) => {
    if (
      m.content.toLowerCase() === 'confirm' ||
      m.content.toLowerCase() === 'confirm keep'
    ) {
      if (m.content.toLowerCase() === 'confirm keep') {
        deleteDays = 0;
      }
      badPeople.forEach(async (mem) => {
        try {
          await server.guild.members.ban(mem, {
            days: deleteDays,
            reason: `Issued by: ${executor.tag}. Reason: ${reason}`,
          });
        } catch (e) {
          await message.channel.send(`Failed to ban: ${mem}`);
        }
      });
      collector.stop('Banned');
      return;
    }
    if (m.content.toLowerCase() == 'cancel') {
      collector.stop('Cancelled');
      return;
    }
    message.channel.send('Invalid response. Type `confirm` or `cancel`');
  });
  collector.on('end', (collected, endReason) => {
    if (endReason == 'Banned') {
      message.channel.send(`✅ Banned ${badPeople.length} people`);
      return;
    } else if (endReason == 'Cancelled') {
      message.channel.send('❌ Cancelled');
      return;
    } else {
      message.channel.send('❌ Failed to confirm');
      return;
    }
  });
};
<commit_msg>mass ban wording<commit_after>module.exports.name = 'raidban';

module.exports.alias = ['banraid', 'raidban'];

module.exports.isAllowed = (message) => {
  return (
    message.member.hasPermission('BAN_MEMBERS') ||
    message.member.roles.cache.has('543721608506900480')
  );
};

module.exports.help =
  ' `,raidban <user or timestamp Discord ID> [--end user or timestamp Discord ID] [--except user-mentions]`\n Ban all the users joined after the mentioned guy. Can also specify the last guy with `--end`. ALL INCLUSIVE. \nExamples:\n`,raidban @NewGuy`\n`,raidban @FirstGuy --end @LastGuy --except @InnocentGuy` will ban @FirstGuy and anyone after that up to and including @LastGuy, except @InnocentGuy';

const Discord = require('discord.js');

module.exports.command = async (message, content, bot, server) => {
  const badPeople = [];
  const executor = message.author;
  let deleteDays = 1;
  const reason = 'Raid Mass Ban';
  let endID = null;
  const endFlag = content.match(/--end\s+([0-9]{17,21})/);
  if (endFlag) {
    content = content.replace(/--end\s+[0-9]{17,21}/, '');
    endID = endFlag[1];
  }
  let [first, exceptions] = content.split('--except');
  const exceptionIDs = exceptions ? exceptions.match(/[0-9]{17,21}/g) : [];
  const firstMatch = first ? first.match(/[0-9]{17,21}/) : null;
  const firstID = firstMatch && firstMatch[0];

  if (!firstID) {
    message.channel.send('Failed to resolve the first user');
    return;
  }
  const firstMem = server.guild.member(firstID);
  let firstMillis;
  if (firstMem && firstMem.joinedAt) {
    firstMillis = firstMem.joinedAt.getTime();
  } else {
    const date = Discord.SnowflakeUtil.deconstruct(firstID).date;
    firstMillis = date.getTime();
  }
  const endMem = endID ? server.guild.member(endID) : null;

  const nowMillis = new Date().getTime();
  if (nowMillis - firstMillis > 86400000) {
    message.channel.send('The first user join date cannot be older than 1 day');
    return;
  }
  let endMillis = nowMillis;
  if (endMem && endMem.joinedAt) {
    endMillis = endMem.joinedAt.getTime();
  } else if (endID) {
    const date = Discord.SnowflakeUtil.deconstruct(endID).date;
    endMillis = date.getTime();
  }
  if (endMillis - firstMillis < 0) {
    message.channel.send('The last guy joined before the first guy');
    return;
  }

  server.guild.members.cache.forEach((mem, memID) => {
    if (!mem.joinedAt) return;
    const memMillis = mem.joinedAt.getTime();
    if (
      memMillis >= firstMillis &&
      memMillis <= endMillis &&
      !exceptionIDs.includes(memID)
    ) {
      badPeople.push(mem);
    }
  });

  if (badPeople.length === 0) {
    message.channel.send('Failed to get members...');
    return;
  }

  const banMessage = `<:hypergeralthinkban:443803651325034507>  **You are banning ${
    badPeople.length
  } people!**  <:hypergeralthinkban:443803651325034507>\n\n${badPeople
    .map((m) => m.toString())
    .join('\n')}\n\nType \`confirm\` or \`cancel\``;
  await message.channel.send(banMessage, { split: true });
  const filter = (m) => m.member.id == executor.id;
  const collector = message.channel.createMessageCollector(filter, {
    time: 45000,
  });
  collector.on('collect', (m) => {
    if (
      m.content.toLowerCase() === 'confirm' ||
      m.content.toLowerCase() === 'confirm keep'
    ) {
      if (m.content.toLowerCase() === 'confirm keep') {
        deleteDays = 0;
      }
      badPeople.forEach(async (mem) => {
        try {
          await server.guild.members.ban(mem, {
            days: deleteDays,
            reason: `Issued by: ${executor.tag}. Reason: ${reason}`,
          });
        } catch (e) {
          await message.channel.send(`Failed to ban: ${mem}`);
        }
      });
      collector.stop('Banned');
      return;
    }
    if (m.content.toLowerCase() == 'cancel') {
      collector.stop('Cancelled');
      return;
    }
    message.channel.send('Invalid response. Type `confirm` or `cancel`');
  });
  collector.on('end', (collected, endReason) => {
    if (endReason == 'Banned') {
      message.channel.send(`✅ Banned ${badPeople.length} people`);
      return;
    } else if (endReason == 'Cancelled') {
      message.channel.send('❌ Cancelled');
      return;
    } else {
      message.channel.send('❌ Failed to confirm');
      return;
    }
  });
};
<|endoftext|>


<commit_before>var Command = require('ronin').Command
var fs = require('fs')
var ipfsAPI = require('ipfs-api')
var path = require('path')

module.exports = Command.extend({
  desc: 'Publish your project',

  run: function (name) {
    try {
      var configPath = path.resolve(process.cwd() + '/ipscend.json')
      fs.statSync(configPath)
      publish()
    } catch (err) {
      console.log('Project must be initiated first, run `ipscend init`')
    }

    function publish () {
      var config = JSON.parse(fs.readFileSync(configPath))
      // TODO check if daemon is running
      var ipfs = ipfsAPI('localhost', '5001')

      ipfs.add(config.path, { recursive: true, 'stream-channels': false }, function (err, res) {
        if (err || !res) {
          return console.error('err', err)
        }

        var version = {
          hash: res[res.length - 2].Hash,
          timestamp: new Date()
        }
        console.log(version)

        console.log('published', config.path, version.hash)

        config.versions.push(version)

        var fd = fs.openSync(configPath, 'w')
        fs.writeSync(fd, JSON.stringify(config, null, '  '), 0, 'utf-8')
      })
    }
  }
})
<commit_msg>Revert "use the second-from-root object returned when publishing"<commit_after>var Command = require('ronin').Command
var fs = require('fs')
var ipfsAPI = require('ipfs-api')
var path = require('path')

module.exports = Command.extend({
  desc: 'Publish your project',

  run: function (name) {
    try {
      var configPath = path.resolve(process.cwd() + '/ipscend.json')
      fs.statSync(configPath)
      publish()
    } catch (err) {
      console.log('Project must be initiated first, run `ipscend init`')
    }

    function publish () {
      var config = JSON.parse(fs.readFileSync(configPath))
      // TODO check if daemon is running
      var ipfs = ipfsAPI('localhost', '5001')

      ipfs.add(config.path, { recursive: true, 'stream-channels': false }, function (err, res) {
        if (err || !res) {
          return console.error('err', err)
        }

        var version = {
          hash: res[res.length - 1].Hash,
          timestamp: new Date()
        }
        console.log(version)

        console.log('published', config.path, version.hash)

        config.versions.push(version)

        var fd = fs.openSync(configPath, 'w')
        fs.writeSync(fd, JSON.stringify(config, null, '  '), 0, 'utf-8')
      })
    }
  }
})
<|endoftext|>


<commit_before>//creates a .tessel folder with ssh keys in your home directory and uses those ssh keys to authorize you to push code to the USB-connected Tessel

var osenv = require('osenv');
var fs = require('fs-extra');
var keygen = require('ssh-keygen');

var Tessel = require('./tessel');
var commands = require('./commands');

var dir = osenv.home() + '/.tessel';
var filename = 'id_rsa';
var filepath = dir + '/' + filename;

Tessel.prototype.provisionTessel = function (opts) {
  var self = this;
  // Check if local .tessel file has keypair, if not, put it there
  setupLocal(function () {
    // Authorize Tessel for SSH
    authTessel(self);
  });
}

// Make sure local computer is set up to authorize with Tessel
function setupLocal (callback) {
  // Check if keypair already in place
  if(!(fs.existsSync(filepath) && fs.existsSync(filepath + '.pub'))) {
    console.log('Creating public and private keys for Tessel authentication...');

    // Generate SSH key
    keygen({}, function(err, out){
      if(err) return console.log('Something went wrong: '+err);
      var privateKey = out.key;
      var publicKey = out.pubKey;

      // Make sure dir exists
      fs.ensureDir(dir, function (err) {
        err && console.log(err);

        filesWritten = 0;

        // Put SSH keys for Tessel in that folder
        fs.writeFile(filepath + '.pub', publicKey, function (err) {
          err && console.log(err);
          fs.chmodSync(filepath + '.pub', '600');
          console.log('Public key written.');
          filesWritten++;
          if (filesWritten == 2) {
            callback && callback(null, true);
          }
        });
        fs.writeFile(filepath, privateKey, function (err) {
          err && console.log(err);
          fs.chmodSync(filepath, '600');
          console.log('Private key written.');
          filesWritten++;
          if (filesWritten == 2) {
            callback && callback(null, true);
          }
        });
      });
    });
  } else {
    callback && callback(null, false);
  }
}

// Put the specified SSH key in Tessel's auth file
function authTessel (tessel) {
  console.log('Authenticating Tessel with public key...');

  var sourceFile = filepath + '.pub';
  var authFile = '/etc/dropbear/authorized_keys';

  // Make sure Tessel has the authFile
  checkAuthFileExists(tessel, authFile, function () {
    // Read the public key
    fs.readFile(filepath + '.pub', {encoding: 'utf-8'}, function (err, pubKey) {
      // See if the public key is already in the authFile
      checkIfKeyInFile(tessel, authFile, pubKey, function () {
        // Copy pubKey into authFile
        copyKey(tessel, authFile, pubKey);
      });
    });
  });
}

function checkAuthFileExists (tessel, authFile, callback) {
  tessel.connection.exec(commands.ensureFileExists(authFile), function (err, remoteProc) {
    remoteProc.stderr.pipe(process.stderr);
    remoteProc.once('close', function () {
      callback && callback();
    });
  });
}

function checkIfKeyInFile (tessel, authFile, pubKey, callback) {
  var tempData = '';
  tessel.connection.exec(commands.readFile(authFile), function (err, remoteProc) {
    err && console.log(err);
    // If Tessel has an error, print it
    remoteProc.stderr.pipe(process.stderr);
    // When we get data
    remoteProc.stdout.on('data', function (data) {
      tempData += data;
    });
    remoteProc.once('close', function () {
      if(tempData.indexOf(pubKey) > -1) {
        console.log('Tessel is already authenticated with this computer.');
        closeAndExit(tessel);
      } else {
        callback && callback();
      }
    });
  });
}

function copyKey (tessel, authFile, pubKey) {
  tessel.connection.exec(commands.appendStdinToFile(authFile), function (err, remoteProc) {
    err && console.log(err);
    // Handle the end of the stream
    remoteProc.once('close', function () {
      console.log('Tessel authenticated with public key.');
      // Close the connection
      closeAndExit(tessel);
    });
    // If Tessel has an error, print it
    remoteProc.stderr.pipe(process.stderr);
    // Send the key
    remoteProc.stdin.end(pubKey);
  });
}

function closeAndExit(tessel) {
  tessel.connection.end(function () {
    process.exit(0);
  });
}

module.exports.setupLocal = setupLocal;
<commit_msg>errors if you try to provision over LAN per https://github.com/tessel/t2-cli/issues/64<commit_after>//creates a .tessel folder with ssh keys in your home directory and uses those ssh keys to authorize you to push code to the USB-connected Tessel

var osenv = require('osenv');
var fs = require('fs-extra');
var keygen = require('ssh-keygen');

var Tessel = require('./tessel');
var commands = require('./commands');

var dir = osenv.home() + '/.tessel';
var filename = 'id_rsa';
var filepath = dir + '/' + filename;

Tessel.prototype.provisionTessel = function (opts) {
  var self = this;
  if(self.connection.connectionType == "USB") {
    // Check if local .tessel file has keypair, if not, put it there
    setupLocal(function () {
      // Authorize Tessel for SSH
      authTessel(self);
    });
  } else {
    console.warn('Tessel must be connected with USB to use this command.');
    closeAndExit(self);
  }
}

// Make sure local computer is set up to authorize with Tessel
function setupLocal (callback) {
  // Check if keypair already in place
  if(!(fs.existsSync(filepath) && fs.existsSync(filepath + '.pub'))) {
    console.log('Creating public and private keys for Tessel authentication...');

    // Generate SSH key
    keygen({}, function(err, out){
      if(err) return console.log('Something went wrong: '+err);
      var privateKey = out.key;
      var publicKey = out.pubKey;

      // Make sure dir exists
      fs.ensureDir(dir, function (err) {
        err && console.log(err);

        filesWritten = 0;

        // Put SSH keys for Tessel in that folder
        fs.writeFile(filepath + '.pub', publicKey, function (err) {
          err && console.log(err);
          fs.chmodSync(filepath + '.pub', '600');
          console.log('Public key written.');
          filesWritten++;
          if (filesWritten == 2) {
            callback && callback(null, true);
          }
        });
        fs.writeFile(filepath, privateKey, function (err) {
          err && console.log(err);
          fs.chmodSync(filepath, '600');
          console.log('Private key written.');
          filesWritten++;
          if (filesWritten == 2) {
            callback && callback(null, true);
          }
        });
      });
    });
  } else {
    callback && callback(null, false);
  }
}

// Put the specified SSH key in Tessel's auth file
function authTessel (tessel) {
  console.log('Authenticating Tessel with public key...');

  var sourceFile = filepath + '.pub';
  var authFile = '/etc/dropbear/authorized_keys';

  // Make sure Tessel has the authFile
  checkAuthFileExists(tessel, authFile, function () {
    // Read the public key
    fs.readFile(filepath + '.pub', {encoding: 'utf-8'}, function (err, pubKey) {
      // See if the public key is already in the authFile
      checkIfKeyInFile(tessel, authFile, pubKey, function () {
        // Copy pubKey into authFile
        copyKey(tessel, authFile, pubKey);
      });
    });
  });
}

function checkAuthFileExists (tessel, authFile, callback) {
  tessel.connection.exec(commands.ensureFileExists(authFile), function (err, remoteProc) {
    remoteProc.stderr.pipe(process.stderr);
    remoteProc.once('close', function () {
      callback && callback();
    });
  });
}

function checkIfKeyInFile (tessel, authFile, pubKey, callback) {
  var tempData = '';
  tessel.connection.exec(commands.readFile(authFile), function (err, remoteProc) {
    err && console.log(err);
    // If Tessel has an error, print it
    remoteProc.stderr.pipe(process.stderr);
    // When we get data
    remoteProc.stdout.on('data', function (data) {
      tempData += data;
    });
    remoteProc.once('close', function () {
      if(tempData.indexOf(pubKey) > -1) {
        console.log('Tessel is already authenticated with this computer.');
        closeAndExit(tessel);
      } else {
        callback && callback();
      }
    });
  });
}

function copyKey (tessel, authFile, pubKey) {
  tessel.connection.exec(commands.appendStdinToFile(authFile), function (err, remoteProc) {
    err && console.log(err);
    // Handle the end of the stream
    remoteProc.once('close', function () {
      console.log('Tessel authenticated with public key.');
      // Close the connection
      closeAndExit(tessel);
    });
    // If Tessel has an error, print it
    remoteProc.stderr.pipe(process.stderr);
    // Send the key
    remoteProc.stdin.end(pubKey);
  });
}

function closeAndExit(tessel) {
  tessel.connection.end(function () {
    process.exit(0);
  });
}

module.exports.setupLocal = setupLocal;
<|endoftext|>


<commit_before>var oo = require('@carbon-io/carbon-core').atom.oo(module)
var tt = require('@carbon-io/carbon-core').testtube

/******************************************************************************
 * @class ServiceTest
 */
module.exports = oo({

  /**********************************************************************
   * _type
   */
  _type: tt.HttpTest,

  /**********************************************************************
   * _C
   */
  _C: function() {
    this.service = undefined
  },

  /**********************************************************************
   * _init
   */
  _init: function() {
    tt.HttpTest.prototype._init.call(this)
  },

  /**********************************************************************
   * setup
   */
  setup: function() {
    this.service.start()
    // XXX: Service.sslOptions is not initialized until start is called
    var sslOptions = this.service.sslOptions
    var scheme = (sslOptions && sslOptions.isEnabled()) ? 'https' : 'http'
    this.baseUrl = `${scheme}://localhost:${this.service.port}`
  },

  /**********************************************************************
   * teardown
   */
  teardown: function() {
    this.service.stop()
  },

})
<commit_msg>suppressServiceLogging<commit_after>var oo = require('@carbon-io/carbon-core').atom.oo(module)
var tt = require('@carbon-io/carbon-core').testtube

/******************************************************************************
 * @class ServiceTest
 */
module.exports = oo({

  /**********************************************************************
   * _type
   */
  _type: tt.HttpTest,

  /**********************************************************************
   * _C
   */
  _C: function() {
    this.service = undefined
    this.suppressServiceLogging = true
  },

  /**********************************************************************
   * _init
   */
  _init: function() {
    tt.HttpTest.prototype._init.call(this)
  },

  /**********************************************************************
   * setup
   */
  setup: function() {
    if (this.suppressServiceLogging) {
      this.service.verbosity = 'fatal'
    }

    this.service.start()
    // XXX: Service.sslOptions is not initialized until start is called
    var sslOptions = this.service.sslOptions
    var scheme = (sslOptions && sslOptions.isEnabled()) ? 'https' : 'http'
    this.baseUrl = `${scheme}://localhost:${this.service.port}`
  },

  /**********************************************************************
   * teardown
   */
  teardown: function() {
    this.service.stop()
  },

})
<|endoftext|>


<commit_before>'use strict';
var DirectivesModule = angular.module('KMC.directives', [
    'colorpicker.module',
    'ui.bootstrap',
    'ui.select2',
    'ui.sortable'
]);
DirectivesModule.directive('timeago', [function () {
    return {
        restrict: 'CA',
        link: function (scope, iElement, iAttrs) {
            if (typeof $.timeago == 'function') {
                scope.$observe('timeago', function (newVal) {
                    if (newVal && !isNaN(newVal)) {
                        var date = scope.timestamp * 1000;
                        iElement.text($.timeago(date));
                    }
                });
            }
        }
    };
}]);
DirectivesModule.directive('hiddenValue', [function () {
    return {
        template: '<input type="hidden" value="{{model}}"/>',
        scope: {
            model: '='
        },
        controller: function ($scope, $element, $attrs) {
            if ($attrs['initvalue']) {
                $scope.model = $attrs['initvalue'];
            }
        },
        restrict: 'EA'
    };
}]);
DirectivesModule.directive('modelRadio', ['menuSvc', function (menuSvc) {
    return {
        restrict: 'EA',
        replace: true,
        require: '?playerRefresh',
        templateUrl: 'template/formcontrols/modelRadio.html',
        scope: {
            'model': '=',
            'strModel': '@model',
            'label': '@',
            'helpnote': '@',
            'require': '@'
        },
        controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
            var menuData = menuSvc.getControlData($attrs.model);
            $scope.options = menuData.options;
            var ngModelCntrl;
            var controls = [];
            return {
                setChoice: function (value) {
                    angular.forEach(controls, function (control) {
                        control.setValue(value);
                    });
                },
                registerControl: function (cntrl) {
                    controls.push(cntrl);
                },
                getValue: function () {
                    return $scope.model;
                },
                regContoller: function (cntrl) {
                    if (!ngModelCntrl)
                        menuSvc.menuScope.playerEdit.$addControl(cntrl);
                    ngModelCntrl = cntrl;
                },
                isRequired: $attrs.require
            };
        }
        ],
        link: function (scope, element, attributes, prController) {
            if (prController) {
                prController.setValueBased();
            }
            if (scope.require) {
                scope.$watch('model', function (newval) { //TODO: change to ngmodel + $setValidity
                    if (!newval)
                        $(element).find('.form-group').addClass('ng-invalid');
                    else {
                        $(element).find('.form-group').removeClass('ng-invalid');
                    }

                });
            }
        }
    };
}])
;

DirectivesModule.directive('dname', function (menuSvc) { // made to help with validation registers dynamic directives with form controller
    return {
        require: '?ngModel',
        priority: 100,
        compile: function (tElement, tAttrs) {
            return function ($scope, $element, $attrs, $ngModelCntrl) {
                if ($ngModelCntrl) {
                    var dname = $scope.$eval($attrs['dname']);
                    $element.attr('name', dname);
                    $ngModelCntrl.$name = dname;
                    menuSvc.menuScope.playerEdit.$addControl($ngModelCntrl);
                }
            };
        }
    };
});
DirectivesModule.directive('valType', function () {
    return {
        restrict: "A",
        link: function ($scope, $element, $attrs) {
            if (($attrs['valType'] == 'url' || $attrs['valType'] == 'email') && window.IE != 8) {
                $element.attr('type', $attrs['valType']);
            }
        }
    };
});
DirectivesModule.directive('modelEdit', ['$modal',
    function ($modal) {
        var modalEditCntrl = ['$scope' , function ($scope) {
            if (typeof $scope.model == 'undefined')
                $scope.model = '';
            $scope.modelValue = $scope.model;
        }];
        return {
            replace: true,
            restrict: 'EA',
            scope: {
                'label': '@',
                'helpnote': '@',
                'model': '=',
                'icon': '@',
                'require': '@',
                'strModel': '=model'
            },
            controller: modalEditCntrl,
            templateUrl: 'template/formcontrols/modelEdit.html',
            compile: function (tElement, tAttr) {
                if (tAttr['endline'] == 'true') {
                    tElement.append('
');
                }
                return function (scope, element, attrs) {
                    scope.doModal = function () {
                        var modal = $modal.open({
                            templateUrl: 'template/dialog/textarea.html',
                            controller: 'ModalInstanceCtrl',
                            resolve: {
                                settings: function () {
                                    return {
                                        'close': function (result, value) {
                                            scope.model = value;
                                            modal.close(result);
                                        },
                                        'title': attrs.label,
                                        'message': scope.model
                                    };
                                }
                            }
                        });
                    };
                };
            }
        };
    }
]);
DirectivesModule.directive('modelTags', [
    'menuSvc',
    function (menuSvc) {
        return {
            replace: true,
            restrict: 'EA',
            scope: {
                'label': '@',
                'model': '=',
                'helpnote': '@',
                'icon': '@',
                'strModel': '=model'
            },
            controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
                $scope.selectOpts = {
                    simple_tags: true,
                    'multiple': true,
                    tokenSeparators: [
                        ',',
                        ' '
                    ]
                };
                $scope.selectOpts['tags'] = menuSvc.doAction($attrs.source);
            }],
            templateUrl: 'template/formcontrols/modelTags.html',
            compile: function (tElement, tAttr) {
                if (tAttr['endline'] == 'true') {
                    tElement.append('
');
                }
                return function (scope, element, attr) {
                };
            }
        };
    }
]);
DirectivesModule.directive('listEntriesThumbs', function () {
    return {
        restrict: 'A',
        controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
            if ($attrs.listEntriesThumbs == 'true') {
                var format = function (player) {
                    if (!player.thumbnailUrl)
                        return player.name;
                    return '' + player.name;
                };
                $scope.addOption({
                    formatResult: format,
                    formatSelection: format,
                    escapeMarkup: function (m) {
                        return m;
                    }
                });
            }
        }]
    };
});
DirectivesModule.directive('parentContainer', ['sortSvc', function (sortSvc) {
    return {
        restrict: 'A',
        controller: function () {
            var cntrl = {
                register: function (container, model) {
                    sortSvc.register(container, model);
                },
                update: function (newVal, oldVal, model) {
                    sortSvc.update(newVal, oldVal, model);
                }
            };
            return cntrl;
        }
    };
}]);
DirectivesModule.directive('sortOrder', [
    'sortSvc',
    function (sortSvc) {
        return {
            restrict: 'EA',
            replace: true,
            scope: {},
            templateUrl: 'template/formcontrols/sortOrder.html',
            controller: ['$scope', function ($scope) {
                $scope.getObjects = function () {
                    $scope.containers = sortSvc.getObjects();
                };
                $scope.getObjects();
                sortSvc.sortScope = $scope;
                $scope.$on('sortContainersChanged', function () {
                    $scope.getObjects();
                });
                $scope.$watchCollection('containers', function (newVal, oldVal) {
                    if (newVal != oldVal) {
                        sortSvc.saveOrder($scope.containers);
                    }
                });
                $scope.sortableOptions = {
                    update: function (e, ui) {
                        cl($scope.containers);
                    },
                    axis: 'y'
                };
            }],
            link: function (scope, element, attrs) {
            }
        };
    }
]);
DirectivesModule.directive('infoAction', ['menuSvc', function (menuSvc) {
    return {
        restrict: 'EA',
        replace: 'true',
        controller: ['$scope', function ($scope) {
            $scope.check = function (action) {
                return menuSvc.checkAction(action);
            };
            $scope.btnAction = function (action) {
                menuSvc.doAction(action);
            };
        }],
        scope: {
            'model': '=',
            'btnLabel': '@',
            'btnClass': '@',
            'action': '@',
            'helpnote': '@',
            'label': '@'
        },
        templateUrl: 'template/formcontrols/infoAction.html'
    };
}]);
DirectivesModule.directive('prettyRadio', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'AC',
        require: ['ngModel', '^modelRadio'],
        transclude: 'element',
        controller: function ($scope, $element, $attrs) {
            $scope.checked = false;
            $scope.setValue = function (value) {
                if (value == $attrs.value) {
                    $scope.checked = true;
                } else
                    $scope.checked = false;
            };
            if ($scope.$eval($attrs['model']) == $attrs.value) {
                $scope.checked = true;
            }
        },
        compile: function (tElement, tAttrs, transclude) {
            return function (scope, iElement, iAttr, cntrls) {
                var ngController = cntrls[0];
                var modelRadioCntrl = cntrls[1];
                var wrapper = $('');
                var clickHandler = $('').appendTo(wrapper);
                modelRadioCntrl.registerControl(scope);
                modelRadioCntrl.regContoller(ngController);
                var inputVal = iAttr.value;
                var watchProp = 'model';
                if (typeof iAttr['model'] != 'undefined') {
                    watchProp = iAttr['model'];
                }
                transclude(scope, function (clone) {
                    return iElement.replaceWith(wrapper).append(clone);
                });
                clickHandler.on('click', function (e) {
                    e.preventDefault();
                    ngController.$setViewValue(inputVal);

                    $rootScope.$safeApply(scope, function () {
                            modelRadioCntrl.setChoice(inputVal);
                        }
                    );
                    return false;
                });
                var formatter = function () {
                    modelRadioCntrl.setChoice(inputVal);
                };
                ngController.$viewChangeListeners.push(formatter);
                scope.$watch('checked', function (newVal) {
                    if (newVal) {
                        clickHandler.addClass('checked');
                    }
                    else
                        clickHandler.removeClass('checked');
                });
            };
        }
    };
}]);
DirectivesModule.directive('divider', [function () {
    return {
        replace: true,
        restrict: 'EA',
        template: '
'
    };
}]);
DirectivesModule.directive('readOnly', ['$filter', function ($filter) {
    return {
        restrict: 'EA',
        replace: 'true',
        scope: {
            model: '=',
            helpnote: '@'
        },
        controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
            if ($attrs['filter']) {
                if (typeof $filter($attrs['filter']) == 'function')
                    $scope.model = $filter($attrs['filter'])($scope.model);
            }
            if ($attrs['initvalue']) {
                if (typeof $scope.model == 'undefined' || $scope.model === '')
                    $scope.model = $attrs['initvalue'];
            }
            $scope.label = $attrs.label + ':';
        }],
        templateUrl: 'template/formcontrols/readOnly.html'
    };
}]);
DirectivesModule.directive('modelButton', ['menuSvc', function (menuSvc) {
    return {
        restrict: 'EA',
        replace: 'true',
        controller: ['$scope', function ($scope) {
            $scope.check = function (action) {
                return menuSvc.checkAction(action);
            };
            $scope.btnAction = function (action) {
                menuSvc.doAction(action);
            };
        }],
        scope: {
            'label': '@',
            'action': '@',
            'btnClass': '@',
            helpnote: '@'
        },
        templateUrl: 'template/formcontrols/modelButton.html'
    };
}]);
DirectivesModule.directive('onFinishRender', [
    '$timeout',
    'requestNotificationChannel',
    function ($timeout, requestNotificationChannel) {
        return {
            restrict: 'A',
            link: function (scope, element, attr) {
                // got last object - finish render and hide the spinner
                if (scope.$last === true) {
                    var timeVar;
                    if (timeVar) {
                        $timeout.cancel(timeVar);
                    }
                    timeVar = $timeout(function () {
                        requestNotificationChannel.requestEnded('list');
                        timeVar = null;
                    });
                }
            }
        };
    }
]);
DirectivesModule.directive("onbeforeunload", ["$window", "$filter", function ($window, $filter) {
    var unloadtext, forms = [];

    function handleOnbeforeUnload() {
        var i, form, isDirty = false;

        for (i = 0; i < forms.length; i++) {
            form = forms[i];

            if (form.scope[form.name].$dirty) {
                isDirty = true;
                break;
            }
        }

        if (isDirty) {
            return unloadtext;
        } else {
            return undefined;
        }
    }

    return function ($scope, $element) {
        if ($element[0].localName !== 'form') {
            throw new Error("onbeforeunload directive must only be set on a angularjs form!");
        }

        forms.push({
            "name": $element[0].name,
            "scope": $scope
        });
        try {
            unloadtext = $filter("translate")("onbeforeunload");
        } catch (err) {
            unloadtext = "";
        }
        var formName = $element[0].name;
        $scope.$watch(formName+'.$dirty', function (newVal, oldVal) {
            if (newVal && newVal != oldVal) {
                $window.onbeforeunload = handleOnbeforeUnload;
            }
        });

    };
}]);<commit_msg>IE8 fix<commit_after>'use strict';
var DirectivesModule = angular.module('KMC.directives', [
    'colorpicker.module',
    'ui.bootstrap',
    'ui.select2',
    'ui.sortable'
]);
DirectivesModule.directive('timeago', [function () {
    return {
        restrict: 'CA',
        link: function (scope, iElement, iAttrs) {
            if (typeof $.timeago == 'function') {
                scope.$observe('timeago', function (newVal) {
                    if (newVal && !isNaN(newVal)) {
                        var date = scope.timestamp * 1000;
                        iElement.text($.timeago(date));
                    }
                });
            }
        }
    };
}]);
DirectivesModule.directive('hiddenValue', [function () {
    return {
        template: '<input type="hidden" value="{{model}}"/>',
        scope: {
            model: '='
        },
        controller: function ($scope, $element, $attrs) {
            if ($attrs['initvalue']) {
                $scope.model = $attrs['initvalue'];
            }
        },
        restrict: 'EA'
    };
}]);
DirectivesModule.directive('modelRadio', ['menuSvc', function (menuSvc) {
    return {
        restrict: 'EA',
        replace: true,
        require: '?playerRefresh',
        templateUrl: 'template/formcontrols/modelRadio.html',
        scope: {
            'model': '=',
            'strModel': '@model',
            'label': '@',
            'helpnote': '@',
            'require': '@'
        },
        controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
            var menuData = menuSvc.getControlData($attrs.model);
            $scope.options = menuData.options;
            var ngModelCntrl;
            var controls = [];
            return {
                setChoice: function (value) {
                    angular.forEach(controls, function (control) {
                        control.setValue(value);
                    });
                },
                registerControl: function (cntrl) {
                    controls.push(cntrl);
                },
                getValue: function () {
                    return $scope.model;
                },
                regContoller: function (cntrl) {
                    if (!ngModelCntrl)
                        menuSvc.menuScope.playerEdit.$addControl(cntrl);
                    ngModelCntrl = cntrl;
                },
                isRequired: $attrs.require
            };
        }
        ],
        link: function (scope, element, attributes, prController) {
            if (prController) {
                prController.setValueBased();
            }
            if (scope.require) {
                scope.$watch('model', function (newval) { //TODO: change to ngmodel + $setValidity
                    if (!newval)
                        $(element).find('.form-group').addClass('ng-invalid');
                    else {
                        $(element).find('.form-group').removeClass('ng-invalid');
                    }

                });
            }
        }
    };
}])
;

DirectivesModule.directive('dname', function (menuSvc) { // made to help with validation registers dynamic directives with form controller
    return {
        require: '?ngModel',
        priority: 100,
        compile: function (tElement, tAttrs) {
            return function ($scope, $element, $attrs, $ngModelCntrl) {
                if ($ngModelCntrl) {
                    var dname = $scope.$eval($attrs['dname']);
                    $element.attr('name', dname);
                    $ngModelCntrl.$name = dname;
                    menuSvc.menuScope.playerEdit.$addControl($ngModelCntrl);
                }
            };
        }
    };
});
DirectivesModule.directive('valType', function () {
    return {
        restrict: "A",
        link: function ($scope, $element, $attrs) {
            if (($attrs['valType'] == 'url' || $attrs['valType'] == 'email') && window.IE != 8) {
                $element.attr('type', $attrs['valType']);
            }
        }
    };
});
DirectivesModule.directive('modelEdit', ['$modal',
    function ($modal) {
        var modalEditCntrl = ['$scope' , function ($scope) {
            if (typeof $scope.model == 'undefined')
                $scope.model = '';
            $scope.modelValue = $scope.model;
        }];
        return {
            replace: true,
            restrict: 'EA',
            scope: {
                'label': '@',
                'helpnote': '@',
                'model': '=',
                'icon': '@',
                'require': '@',
                'strModel': '=model'
            },
            controller: modalEditCntrl,
            templateUrl: 'template/formcontrols/modelEdit.html',
            compile: function (tElement, tAttr) {
                if (tAttr['endline'] == 'true') {
                    tElement.append('
');
                }
                return function (scope, element, attrs) {
                    scope.doModal = function () {
                        var modal = $modal.open({
                            templateUrl: 'template/dialog/textarea.html',
                            controller: 'ModalInstanceCtrl',
                            resolve: {
                                settings: function () {
                                    return {
                                        'close': function (result, value) {
                                            scope.model = value;
                                            modal.close(result);
                                        },
                                        'title': attrs.label,
                                        'message': scope.model
                                    };
                                }
                            }
                        });
                    };
                };
            }
        };
    }
]);
DirectivesModule.directive('modelTags', [
    'menuSvc',
    function (menuSvc) {
        return {
            replace: true,
            restrict: 'EA',
            scope: {
                'label': '@',
                'model': '=',
                'helpnote': '@',
                'icon': '@',
                'strModel': '=model'
            },
            controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
                $scope.selectOpts = {
                    simple_tags: true,
                    'multiple': true,
                    tokenSeparators: [
                        ',',
                        ' '
                    ]
                };
                $scope.selectOpts['tags'] = menuSvc.doAction($attrs.source);
            }],
            templateUrl: 'template/formcontrols/modelTags.html',
            compile: function (tElement, tAttr) {
                if (tAttr['endline'] == 'true') {
                    tElement.append('
');
                }
                return function (scope, element, attr) {
                };
            }
        };
    }
]);
DirectivesModule.directive('listEntriesThumbs', function () {
    return {
        restrict: 'A',
        controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
            if ($attrs.listEntriesThumbs == 'true') {
                var format = function (player) {
                    if (!player.thumbnailUrl)
                        return player.name;
                    return '' + player.name;
                };
                $scope.addOption({
                    formatResult: format,
                    formatSelection: format,
                    escapeMarkup: function (m) {
                        return m;
                    }
                });
            }
        }]
    };
});
DirectivesModule.directive('parentContainer', ['sortSvc', function (sortSvc) {
    return {
        restrict: 'A',
        controller: function () {
            var cntrl = {
                register: function (container, model) {
                    sortSvc.register(container, model);
                },
                update: function (newVal, oldVal, model) {
                    sortSvc.update(newVal, oldVal, model);
                }
            };
            return cntrl;
        }
    };
}]);
DirectivesModule.directive('sortOrder', [
    'sortSvc',
    function (sortSvc) {
        return {
            restrict: 'EA',
            replace: true,
            scope: {},
            templateUrl: 'template/formcontrols/sortOrder.html',
            controller: ['$scope', function ($scope) {
                $scope.getObjects = function () {
                    $scope.containers = sortSvc.getObjects();
                };
                $scope.getObjects();
                sortSvc.sortScope = $scope;
                $scope.$on('sortContainersChanged', function () {
                    $scope.getObjects();
                });
                $scope.$watchCollection('containers', function (newVal, oldVal) {
                    if (newVal != oldVal) {
                        sortSvc.saveOrder($scope.containers);
                    }
                });
                $scope.sortableOptions = {
                    update: function (e, ui) {
                        cl($scope.containers);
                    },
                    axis: 'y'
                };
            }],
            link: function (scope, element, attrs) {
            }
        };
    }
]);
DirectivesModule.directive('infoAction', ['menuSvc', function (menuSvc) {
    return {
        restrict: 'EA',
        replace: 'true',
        controller: ['$scope', function ($scope) {
            $scope.check = function (action) {
                return menuSvc.checkAction(action);
            };
            $scope.btnAction = function (action) {
                menuSvc.doAction(action);
            };
        }],
        scope: {
            'model': '=',
            'btnLabel': '@',
            'btnClass': '@',
            'action': '@',
            'helpnote': '@',
            'label': '@'
        },
        templateUrl: 'template/formcontrols/infoAction.html'
    };
}]);
DirectivesModule.directive('prettyRadio', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'AC',
        require: ['ngModel', '^modelRadio'],
        transclude: 'element',
        controller: function ($scope, $element, $attrs) {
            $scope.checked = false;
            $scope.setValue = function (value) {
                if (value == $attrs.value) {
                    $scope.checked = true;
                } else
                    $scope.checked = false;
            };
            if ($scope.$eval($attrs['model']) == $attrs.value) {
                $scope.checked = true;
            }
        },
        compile: function (tElement, tAttrs, transclude) {
            return function (scope, iElement, iAttr, cntrls) {
                var ngController = cntrls[0];
                var modelRadioCntrl = cntrls[1];
                var wrapper = $('');
                var clickHandler = $('').appendTo(wrapper);
                modelRadioCntrl.registerControl(scope);
                modelRadioCntrl.regContoller(ngController);
                var inputVal = iAttr.value;
                var watchProp = 'model';
                if (typeof iAttr['model'] != 'undefined') {
                    watchProp = iAttr['model'];
                }
                transclude(scope, function (clone) {
                    return iElement.replaceWith(wrapper).append(clone);
                });
                clickHandler.on('click', function (e) {
                    e.preventDefault();
                    ngController.$setViewValue(inputVal);

                    $rootScope.$safeApply(scope, function () {
                            modelRadioCntrl.setChoice(inputVal);
                        }
                    );
                    return false;
                });
                var formatter = function () {
                    modelRadioCntrl.setChoice(inputVal);
                };
                ngController.$viewChangeListeners.push(formatter);
                scope.$watch('checked', function (newVal) {
                    if (newVal) {
                        clickHandler.addClass('checked');
                    }
                    else
                        clickHandler.removeClass('checked');
                });
            };
        }
    };
}]);
DirectivesModule.directive('divider', [function () {
    return {
        replace: true,
        restrict: 'EA',
        template: '
'
    };
}]);
DirectivesModule.directive('readOnly', ['$filter', function ($filter) {
    return {
        restrict: 'EA',
        replace: 'true',
        scope: {
            model: '=',
            helpnote: '@'
        },
        controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
            if ($attrs['filter']) {
                if (typeof $filter($attrs['filter']) == 'function')
                    $scope.model = $filter($attrs['filter'])($scope.model);
            }
            if ($attrs['initvalue']) {
                if (typeof $scope.model == 'undefined' || $scope.model === '')
                    $scope.model = $attrs['initvalue'];
            }
            $scope.label = $attrs.label + ':';
        }],
        templateUrl: 'template/formcontrols/readOnly.html'
    };
}]);
DirectivesModule.directive('modelButton', ['menuSvc', function (menuSvc) {
    return {
        restrict: 'EA',
        replace: 'true',
        controller: ['$scope', function ($scope) {
            $scope.check = function (action) {
                return menuSvc.checkAction(action);
            };
            $scope.btnAction = function (action) {
                menuSvc.doAction(action);
            };
        }],
        scope: {
            'label': '@',
            'action': '@',
            'btnClass': '@',
            helpnote: '@'
        },
        templateUrl: 'template/formcontrols/modelButton.html'
    };
}]);
DirectivesModule.directive('onFinishRender', [
    '$timeout',
    'requestNotificationChannel',
    function ($timeout, requestNotificationChannel) {
        return {
            restrict: 'A',
            link: function (scope, element, attr) {
                // got last object - finish render and hide the spinner
                if (scope.$last === true) {
                    var timeVar;
                    if (timeVar) {
                        $timeout.cancel(timeVar);
                    }
                    timeVar = $timeout(function () {
                        requestNotificationChannel.requestEnded('list');
                        timeVar = null;
                    });
                }
            }
        };
    }
]);
DirectivesModule.directive("onbeforeunload", ["$window", "$filter", function ($window, $filter) {
    var unloadtext, forms = [];

    function handleOnbeforeUnload() {
        var i, form, isDirty = false;

        for (i = 0; i < forms.length; i++) {
            form = forms[i];

            if (form.scope[form.name].$dirty) {
                isDirty = true;
                break;
            }
        }

        if (isDirty) {
            return unloadtext;
        } else {
            return undefined;
        }
    }

    return function ($scope, $element) {
        if ($element[0].nodeName.toLowerCase() !== 'form') {
            throw new Error("onbeforeunload directive must only be set on a angularjs form!");
        }

        forms.push({
            "name": $element[0].name,
            "scope": $scope
        });
        try {
            unloadtext = $filter("translate")("onbeforeunload");
        } catch (err) {
            unloadtext = "";
        }
        var formName = $element[0].name;
        $scope.$watch(formName+'.$dirty', function (newVal, oldVal) {
            if (newVal && newVal != oldVal) {
                $window.onbeforeunload = handleOnbeforeUnload;
            }
        });

    };
}]);<|endoftext|>