<commit_before>#!/usr/bin/env node

var fsevents        = require('fsevents'),
    fs              = require('fs'),
    extend          = require('util')._extend,
    http            = require('http'),
    Agent           = require('agentkeepalive'),
    getRelativePath = require('path').relative,
    Minimatch       = require('minimatch').Minimatch,
    async           = require('async'),
    colors          = require('colors/safe'),

    config          = {
        debug:      false,
        logIgnored: false,
        localDir:   '.',

        webdav: {
            ssl: false
        },

        ignore: {
            global: [],
            watch:  [],
            sync:   [],
            git:    [],
        },

        sound: {
            error:   'Basso',
            success: 'Submarine'
        }
    },

    ignoreRe        = {},
    watcher,
    movedOut        = null,
    DEBUG           = true,
    drainSound = null;

DEBUG = !config.debug;

// Merge default configuration options with config.json if present
if (fs.existsSync('./config.json')) {
    config = extend(config, require('./config.json'));
}

// Build regular expressions from globs
for (var ignoreType in config.ignore) {
    ignoreRe[ignoreType] = new RegExp(config.ignore[ignoreType].map(function (glob) {
        return new Minimatch(glob).makeRe().source;
    }).join('|'), 'm');
}

function playSound(sound) {
    sound = sound || config.sound.success;
    require('child_process').spawn('afplay', ['/System/Library/Sounds/' + sound + '.aiff']);
}

function shouldIgnore(event, path) {
    var events = ['global'];

    if (typeof path !== 'string') {
        path = event;
    } else {
        events.push(event);
    }

    for (var x = 0, len = events.length; x < len; x++) {
        if (ignoreRe[events[x]] && ignoreRe[events[x]].test(path)) {
            return true;
        }
    }

    if (event === 'sync') {
        // HACK: Do not try to sync files to the root directory
        return path.indexOf('/') === -1;
    }

    return false;
}

watcher = fsevents(config.localDir);

var keepaliveAgent = new Agent({
    maxSockets:       100,
    maxFreeSockets:   10,
    timeout:          120000,
    keepAliveTimeout: 60000
});

var q = async.queue(function (task, callback) {
    webDavRequest(task.verb, task.dst, task.src, function(err) {
        task.cb(err);
        callback();
    });
}, 1);

q.drain = function() {
    if (drainSound) {
        playSound(drainSound);
    }
};

function webDavRequest(verb, destination, file, callback) {
    var fileStream,
        request,
        headers = {};

    if (file) {
        if (/move/i.test(verb)) {
            headers['Destination'] = config.webdav.path + '/' + destination;
            destination = file;
        } else {
            fileStream = fs.createReadStream(file);
            headers['Content-Length'] = fs.statSync(file).size;
        }
    }

    request = http.request({
        host:    config.webdav.hostname,
        port:    config.webdav.ssl ? 443 : 80,
        method:  verb,
        path:    config.webdav.path + '/' + destination,
        headers: headers,
        agent:   keepaliveAgent,
        auth:    config.webdav.username + ':' + config.webdav.password
    });

    request.on("response", function (res) {
        // Ignore when a delete fails due to a 404
        if (res.statusCode >= 400 && !(verb === 'DELETE' && res.statusCode == 404) && // delete a file that doesn't exist
            !(verb === 'MKCOL' && res.statusCode == 405)  // make a directory that already exists
        ) {
            res.on('end', function () {
                callback(new Error("HTTP " + verb + " failed with code " + res.statusCode + " for " + request.path));
            });
        } else {
            res.on('end', callback);
        }

        res.resume();
    });

    request.on('error', callback);

    if (fileStream) {
        fileStream.pipe(request);
    } else {
        request.end();
    }
}

watcher.on('change', function (path, info) {
    var verb, src, dst, ignore,
        isDir = info.type === 'directory',
        relPath = getRelativePath(__dirname, path);

    DEBUG || console.log(info);

    // Add trailing slash to directories
    if (isDir) {
        path = path + '/';
        info.path = path;
        // HACK: fsevent is passing an unknown event for directory creation (deleted works)
        if (info.event === 'unknown') {
            // HACK: fsevent passes an unknown event for directory chowning
            if (info.changes.inode || info.changes.access || info.changes.xattrs || info.changes.finder) {
                console.warn('Ignoring chown/chmod to: ' + path);
                DEBUG || console.log(info);
                return;
            }
            info.event = 'created';
        }
    }

    dst = relPath;
    ignore = shouldIgnore('watch', relPath);

    switch (info.event) {
        case 'modified':
        case 'created':
            verb = isDir ? 'MKCOL' : 'PUT';
            src = path;
            break;
        case 'deleted':
            verb = 'DELETE';
            dst = null;
            break;
        case 'moved-in':
            if (movedOut) {
                src = getRelativePath(__dirname, movedOut);
                dst = relPath;
                movedOut = null;
            }
            verb = 'MOVE';
            break;
        case 'moved-out':
            movedOut = path;
            break;
    }

    if (verb) {
        // Do not log ignored watch events if logIgnored is false
        if (ignore && config.logIgnored === false) {
            return;
        }

        if (verb === 'MKCOL' || verb === 'DELETE') {
            path = relPath;
            dst = path;
            src = null;
        }

        // File was ignored in either global or watch
        if (ignore) {
            console.log((ignore ? colors.yellow('[IGNORED] ') : '') + verb + ': ' + relPath + (dst ? ' -> ' + dst : ''));
            return;
        }

        // TODO: Memoize should ignore
        if (!shouldIgnore('sync', relPath)) {
            q.push({
                verb: verb, dst: dst, src: src, cb: function (err) {
                    if (err) {
                        playSound(config.sound.error);
                        console.log(colors.red('[FAILED ] ') + verb + ': ' + relPath + (dst ? ' -> ' + dst : '') + '(' + err + ')');
                        return;
                    }

                    drainSound = (drainSound === null) ? config.sound.success : drainSound;
                    console.log(colors.green('[SUCCESS] ') + verb + ': ' + relPath + (dst ? ' -> ' + dst : ''));
                }
            });
        }
    }

});

watcher.start();
<commit_msg>keep paths relative to working directory rather than watcher script<commit_after>#!/usr/bin/env node

var fsevents        = require('fsevents'),
    fs              = require('fs'),
    extend          = require('util')._extend,
    http            = require('http'),
    Agent           = require('agentkeepalive'),
    getRelativePath = require('path').relative,
    Minimatch       = require('minimatch').Minimatch,
    async           = require('async'),
    colors          = require('colors/safe'),

    config          = {
        debug:      false,
        logIgnored: false,
        localDir:   '.',

        webdav: {
            ssl: false
        },

        ignore: {
            global: [],
            watch:  [],
            sync:   [],
            git:    [],
        },

        sound: {
            error:   'Basso',
            success: 'Submarine'
        }
    },

    ignoreRe        = {},
    watcher,
    movedOut        = null,
    DEBUG           = true,
    drainSound = null;

DEBUG = !config.debug;

// Merge default configuration options with config.json if present
if (fs.existsSync(config.localDir + '/config.json')) {
    config = extend(config, JSON.parse(fs.readFileSync(config.localDir + '/config.json')));
}

// Build regular expressions from globs
for (var ignoreType in config.ignore) {
    ignoreRe[ignoreType] = new RegExp(config.ignore[ignoreType].map(function (glob) {
        return new Minimatch(glob).makeRe().source;
    }).join('|'), 'm');
}

function playSound(sound) {
    sound = sound || config.sound.success;
    require('child_process').spawn('afplay', ['/System/Library/Sounds/' + sound + '.aiff']);
}

function shouldIgnore(event, path) {
    var events = ['global'];

    if (typeof path !== 'string') {
        path = event;
    } else {
        events.push(event);
    }

    for (var x = 0, len = events.length; x < len; x++) {
        if (ignoreRe[events[x]] && ignoreRe[events[x]].test(path)) {
            return true;
        }
    }

    if (event === 'sync') {
        // HACK: Do not try to sync files to the root directory
        return path.indexOf('/') === -1;
    }

    return false;
}

watcher = fsevents(config.localDir);

var keepaliveAgent = new Agent({
    maxSockets:       100,
    maxFreeSockets:   10,
    timeout:          120000,
    keepAliveTimeout: 60000
});

var q = async.queue(function (task, callback) {
    webDavRequest(task.verb, task.dst, task.src, function(err) {
        task.cb(err);
        callback();
    });
}, 1);

q.drain = function() {
    if (drainSound) {
        playSound(drainSound);
    }
};

function webDavRequest(verb, destination, file, callback) {
    var fileStream,
        request,
        headers = {};

    if (file) {
        if (/move/i.test(verb)) {
            headers['Destination'] = config.webdav.path + '/' + destination;
            destination = file;
        } else {
            fileStream = fs.createReadStream(file);
            headers['Content-Length'] = fs.statSync(file).size;
        }
    }

    request = http.request({
        host:    config.webdav.hostname,
        port:    config.webdav.ssl ? 443 : 80,
        method:  verb,
        path:    config.webdav.path + '/' + destination,
        headers: headers,
        agent:   keepaliveAgent,
        auth:    config.webdav.username + ':' + config.webdav.password
    });

    request.on("response", function (res) {
        // Ignore when a delete fails due to a 404
        if (res.statusCode >= 400 && !(verb === 'DELETE' && res.statusCode == 404) && // delete a file that doesn't exist
            !(verb === 'MKCOL' && res.statusCode == 405)  // make a directory that already exists
        ) {
            res.on('end', function () {
                callback(new Error("HTTP " + verb + " failed with code " + res.statusCode + " for " + request.path));
            });
        } else {
            res.on('end', callback);
        }

        res.resume();
    });

    request.on('error', callback);

    if (fileStream) {
        fileStream.pipe(request);
    } else {
        request.end();
    }
}

watcher.on('change', function (path, info) {
    var verb, src, dst, ignore,
        isDir = info.type === 'directory',
        relPath = getRelativePath(config.localDir, path);

    DEBUG || console.log(info);

    // Add trailing slash to directories
    if (isDir) {
        path = path + '/';
        info.path = path;
        // HACK: fsevent is passing an unknown event for directory creation (deleted works)
        if (info.event === 'unknown') {
            // HACK: fsevent passes an unknown event for directory chowning
            if (info.changes.inode || info.changes.access || info.changes.xattrs || info.changes.finder) {
                console.warn('Ignoring chown/chmod to: ' + path);
                DEBUG || console.log(info);
                return;
            }
            info.event = 'created';
        }
    }

    dst = relPath;
    ignore = shouldIgnore('watch', relPath);

    switch (info.event) {
        case 'modified':
        case 'created':
            verb = isDir ? 'MKCOL' : 'PUT';
            src = path;
            break;
        case 'deleted':
            verb = 'DELETE';
            dst = null;
            break;
        case 'moved-in':
            if (movedOut) {
                src = getRelativePath(config.localDir, movedOut);
                dst = relPath;
                movedOut = null;
            }
            verb = 'MOVE';
            break;
        case 'moved-out':
            movedOut = path;
            break;
    }

    if (verb) {
        // Do not log ignored watch events if logIgnored is false
        if (ignore && config.logIgnored === false) {
            return;
        }

        if (verb === 'MKCOL' || verb === 'DELETE') {
            path = relPath;
            dst = path;
            src = null;
        }

        // File was ignored in either global or watch
        if (ignore) {
            console.log((ignore ? colors.yellow('[IGNORED] ') : '') + verb + ': ' + relPath + (dst ? ' -> ' + dst : ''));
            return;
        }

        // TODO: Memoize should ignore
        if (!shouldIgnore('sync', relPath)) {
            q.push({
                verb: verb, dst: dst, src: src, cb: function (err) {
                    if (err) {
                        playSound(config.sound.error);
                        console.log(colors.red('[FAILED ] ') + verb + ': ' + relPath + (dst ? ' -> ' + dst : '') + '(' + err + ')');
                        return;
                    }

                    drainSound = (drainSound === null) ? config.sound.success : drainSound;
                    console.log(colors.green('[SUCCESS] ') + verb + ': ' + relPath + (dst ? ' -> ' + dst : ''));
                }
            });
        }
    }

});

watcher.start();
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2007-2011 Parisson
 * Copyright (c) 2011 Riccardo Zaccarelli <riccardo.zaccarelli@gmail.com>
 *
 * This file is part of TimeSide.
 *
 * TimeSide is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * TimeSide is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Riccardo Zaccarelli <riccardo.zaccarelli@gmail.com>
 */

/**
 * Class for managing playlists in telemeta.
 * Requires jQuery and PopupDiv
 */

//default PopupDiv properties for playlists (mainly for css appearence)
PopupDiv.popupClass = 'control component';
PopupDiv.popupCss = {
    'border': '1px solid #999',
    'padding': '1ex'
};
PopupDiv.okButtonTitle = 'Ok';
PopupDiv.okButtonClass = 'component_icon button icon_ok';
PopupDiv.closeButtonTitle = '';
PopupDiv.closeButtonClass = 'markersdivDelete';
PopupDiv.defaultCloseOperation = 'remove';
PopupDiv.focusable = true;
PopupDiv.listItemClass = "component_icon list_item icon_playlist";

var playlistUtils = {
    playlists : [],
    id: '', // ID var: used to edit playlist
    title: '',
    description: '',
    state: 'stop', // state var: to state play or pause glyphicon
    playing: '', // playing var: used to know if an audio is already playing or not
    audio: new Audio(),

    addPlaylist: function (name, id) {
        this.playlists.push({
            'name': name,
            'id': id
        });
    },

    addEditPlaylist: function (id, title, description) {
        this.playlists.push({
            'id': id,
            'title': title,
            'description': description,
        });
    },

    addNewPlaylist: function(){
        this.add({
            'title': $('#titleAdd').val(),
            'description': $('#descriptionAdd').val(),
        });
    },

    // function to change global var ID (used when edit button is pressed)
    editVar: function(id){
        this.id = id;
        for (var i=0; i<this.playlists.length; i++){
            if (this.playlists[i].id == id){
                $('#titleEdit').val(this.playlists[i].title);
                $('#descriptionEdit').val(this.playlists[i].description);
            }
        }
    },

    editPlaylist: function(){
        this.update({
            'public_id': this.id,
            'title': $('#titleEdit').val(),
            'description': $('#descriptionEdit').val(),
        });
        this.id = ""; // init ID
    },

    loadAudio: function(resElem){
        this.audio.src = resElem;
        this.audio.play();
    },

    stopAudio: function(){
        this.audio.pause();
    },

    changeGlyph: function(resElem){
        //wait image element
        var waitImg = "";
        //load filepath when the elment id is the public_id of resource element.
       if(resElem.indexOf("/")==-1){
           $('#'+resElem).removeClass().append(waitImg);
           json_sync([resElem, "mp3"], "telemeta.get_item_export_url", function (data) {
               $('#'+resElem).attr('id', data.result);
               resElem = data.result;
               console.log(data.result);
           });
       }
       if(this.playing === '' || this.playing === resElem){
           if(this.state === 'stop'){
               //if wait image is not displayed
               if($('#wait').length==0){
                   $('[id="'+resElem+'"]').append(waitImg);
               }
               this.state = 'play';
               document.getElementById(resElem).setAttribute("class", "glyphicon glyphicon-pause");
               playlistUtils.loadAudio(resElem);
               this.playing = resElem;
           }
           else if(this.state === 'play'){
               this.state = 'stop';
               document.getElementById(resElem).setAttribute("class", "glyphicon glyphicon-play");
               playlistUtils.stopAudio();
               this.playing = '';
           }
       }
       else{
           playlistUtils.stopAudio();
           this.state = 'stop';
           document.getElementById(this.playing).setAttribute("class", "glyphicon glyphicon-play");
           this.playing = '';
           playlistUtils.changeGlyph(resElem);
       }
    },

    /**
     * Returns an uniqid by creating the current local time in millisecond + a random number. Used for markers and some json calls
     * Copied from Timeside.utils.uniqid (Timeside might NOT ALWAYS be loaded, see home.html when user is authenitcated)
     *
     */
    uniqid: function () {
        var d = new Date();
        return new String(d.getTime() + '' + Math.floor(Math.random() * 1000000)).substr(0, 18);
    },

    add: function (dictionary) {

        if (dictionary.public_id === undefined) {
            dictionary.public_id = this.uniqid();
        }
        if (dictionary.user === undefined) {
            dictionary.user = CURRENT_USER_NAME;
        }

        json([dictionary], 'telemeta.add_playlist', function () {
            window.location.reload();
        });
    },

    remove: function (id) {
        json([id], 'telemeta.del_playlist', function () {
            window.location.reload();
        });
    },

    removeResource: function (id, range_playlist) {
        json([id, range_playlist], 'telemeta.del_playlist_resource', function (data) {
            var id = data.result;
            window.location.pathname = '/desk/lists/' + id;
        });
    },

    update: function (dictionary) {
        json([dictionary], 'telemeta.update_playlist', function () {
            window.location.reload();
        });
    },

    /*shows the popup for adding a resource to a playlist*/
    showAddResourceToPlaylist: function (anchorElement, resourceType, objectId, optionalOkMessage) {
        var ar = [];
        var pl = this;
        var playlists = this.playlists;

        for(var i=0; i< playlists.length; i++){
            ar.push(playlists[i].name);
        }

        if(!ar.length){
            this.showAdd(anchorElement);
        }

        //var addFcn = this.addResourceToPlaylist;
        new PopupDiv({
            invoker: anchorElement,
            content: ar,
            onOk: function (data) {
                var val = data.selIndex;
                var callbackok = undefined;

                if (optionalOkMessage) {
                    callbackok = function () {
                        localStorage['messOkPlaylist'] = optionalOkMessage;
                        localStorage['displayOkPlaylist']=true;
                        window.location.reload();
                    }
                }
                pl.addResourceToPlaylist.apply(pl, [playlists[val].id, resourceType, objectId, callbackok]);
            }
        }).show();

    },

    //resourceType can be: 'collection', 'item', 'marker'
    addResourceToPlaylist: function (playlistId, resourceType, objectId, callbackOnSuccess, callbackOnError) {
        var send = {
            'public_id': this.uniqid(),
            'resource_type': resourceType,
            'resource_id': objectId
        };
        json([playlistId, send], 'telemeta.add_playlist_resource', callbackOnSuccess, callbackOnError);
    },

    messageOk: function () {
        if (localStorage['displayOkPlaylist']) {
            var p = new PopupDiv({
                content: "
" + localStorage['messOkPlaylist']+ "
",
                focusable: false

            });
            p.bind('show', function () {
                this.setTimeout('close', 1500); //this refers to p
            });
            p.show();
            localStorage.removeItem('displayOkPlaylist');
            localStorage.removeItem('messOkPlaylist');
        }

    }
}

$(function () {
    //event in order to remove wait image when audio is playing
    playlistUtils.audio.onplay = function () {
        $('#wait').remove();
    }
})
<commit_msg>Remove log<commit_after>/*
 * Copyright (C) 2007-2011 Parisson
 * Copyright (c) 2011 Riccardo Zaccarelli <riccardo.zaccarelli@gmail.com>
 *
 * This file is part of TimeSide.
 *
 * TimeSide is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * TimeSide is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Riccardo Zaccarelli <riccardo.zaccarelli@gmail.com>
 */

/**
 * Class for managing playlists in telemeta.
 * Requires jQuery and PopupDiv
 */

//default PopupDiv properties for playlists (mainly for css appearence)
PopupDiv.popupClass = 'control component';
PopupDiv.popupCss = {
    'border': '1px solid #999',
    'padding': '1ex'
};
PopupDiv.okButtonTitle = 'Ok';
PopupDiv.okButtonClass = 'component_icon button icon_ok';
PopupDiv.closeButtonTitle = '';
PopupDiv.closeButtonClass = 'markersdivDelete';
PopupDiv.defaultCloseOperation = 'remove';
PopupDiv.focusable = true;
PopupDiv.listItemClass = "component_icon list_item icon_playlist";

var playlistUtils = {
    playlists : [],
    id: '', // ID var: used to edit playlist
    title: '',
    description: '',
    state: 'stop', // state var: to state play or pause glyphicon
    playing: '', // playing var: used to know if an audio is already playing or not
    audio: new Audio(),

    addPlaylist: function (name, id) {
        this.playlists.push({
            'name': name,
            'id': id
        });
    },

    addEditPlaylist: function (id, title, description) {
        this.playlists.push({
            'id': id,
            'title': title,
            'description': description,
        });
    },

    addNewPlaylist: function(){
        this.add({
            'title': $('#titleAdd').val(),
            'description': $('#descriptionAdd').val(),
        });
    },

    // function to change global var ID (used when edit button is pressed)
    editVar: function(id){
        this.id = id;
        for (var i=0; i<this.playlists.length; i++){
            if (this.playlists[i].id == id){
                $('#titleEdit').val(this.playlists[i].title);
                $('#descriptionEdit').val(this.playlists[i].description);
            }
        }
    },

    editPlaylist: function(){
        this.update({
            'public_id': this.id,
            'title': $('#titleEdit').val(),
            'description': $('#descriptionEdit').val(),
        });
        this.id = ""; // init ID
    },

    loadAudio: function(resElem){
        this.audio.src = resElem;
        this.audio.play();
    },

    stopAudio: function(){
        this.audio.pause();
    },

    changeGlyph: function(resElem){
        //wait image element
        var waitImg = "";
        //load filepath when the elment id is the public_id of resource element.
       if(resElem.indexOf("/")==-1){
           $('#'+resElem).removeClass().append(waitImg);
           json_sync([resElem, "mp3"], "telemeta.get_item_export_url", function (data) {
               $('#'+resElem).attr('id', data.result);
               resElem = data.result;
           });
       }
       if(this.playing === '' || this.playing === resElem){
           if(this.state === 'stop'){
               //if wait image is not displayed
               if($('#wait').length==0){
                   $('[id="'+resElem+'"]').append(waitImg);
               }
               this.state = 'play';
               document.getElementById(resElem).setAttribute("class", "glyphicon glyphicon-pause");
               playlistUtils.loadAudio(resElem);
               this.playing = resElem;
           }
           else if(this.state === 'play'){
               this.state = 'stop';
               document.getElementById(resElem).setAttribute("class", "glyphicon glyphicon-play");
               playlistUtils.stopAudio();
               this.playing = '';
           }
       }
       else{
           playlistUtils.stopAudio();
           this.state = 'stop';
           document.getElementById(this.playing).setAttribute("class", "glyphicon glyphicon-play");
           this.playing = '';
           playlistUtils.changeGlyph(resElem);
       }
    },

    /**
     * Returns an uniqid by creating the current local time in millisecond + a random number. Used for markers and some json calls
     * Copied from Timeside.utils.uniqid (Timeside might NOT ALWAYS be loaded, see home.html when user is authenitcated)
     *
     */
    uniqid: function () {
        var d = new Date();
        return new String(d.getTime() + '' + Math.floor(Math.random() * 1000000)).substr(0, 18);
    },

    add: function (dictionary) {

        if (dictionary.public_id === undefined) {
            dictionary.public_id = this.uniqid();
        }
        if (dictionary.user === undefined) {
            dictionary.user = CURRENT_USER_NAME;
        }

        json([dictionary], 'telemeta.add_playlist', function () {
            window.location.reload();
        });
    },

    remove: function (id) {
        json([id], 'telemeta.del_playlist', function () {
            window.location.reload();
        });
    },

    removeResource: function (id, range_playlist) {
        json([id, range_playlist], 'telemeta.del_playlist_resource', function (data) {
            var id = data.result;
            window.location.pathname = '/desk/lists/' + id;
        });
    },

    update: function (dictionary) {
        json([dictionary], 'telemeta.update_playlist', function () {
            window.location.reload();
        });
    },

    /*shows the popup for adding a resource to a playlist*/
    showAddResourceToPlaylist: function (anchorElement, resourceType, objectId, optionalOkMessage) {
        var ar = [];
        var pl = this;
        var playlists = this.playlists;

        for(var i=0; i< playlists.length; i++){
            ar.push(playlists[i].name);
        }

        if(!ar.length){
            this.showAdd(anchorElement);
        }

        //var addFcn = this.addResourceToPlaylist;
        new PopupDiv({
            invoker: anchorElement,
            content: ar,
            onOk: function (data) {
                var val = data.selIndex;
                var callbackok = undefined;

                if (optionalOkMessage) {
                    callbackok = function () {
                        localStorage['messOkPlaylist'] = optionalOkMessage;
                        localStorage['displayOkPlaylist']=true;
                        window.location.reload();
                    }
                }
                pl.addResourceToPlaylist.apply(pl, [playlists[val].id, resourceType, objectId, callbackok]);
            }
        }).show();

    },

    //resourceType can be: 'collection', 'item', 'marker'
    addResourceToPlaylist: function (playlistId, resourceType, objectId, callbackOnSuccess, callbackOnError) {
        var send = {
            'public_id': this.uniqid(),
            'resource_type': resourceType,
            'resource_id': objectId
        };
        json([playlistId, send], 'telemeta.add_playlist_resource', callbackOnSuccess, callbackOnError);
    },

    messageOk: function () {
        if (localStorage['displayOkPlaylist']) {
            var p = new PopupDiv({
                content: "
" + localStorage['messOkPlaylist']+ "
",
                focusable: false

            });
            p.bind('show', function () {
                this.setTimeout('close', 1500); //this refers to p
            });
            p.show();
            localStorage.removeItem('displayOkPlaylist');
            localStorage.removeItem('messOkPlaylist');
        }

    }
}

$(function () {
    //event in order to remove wait image when audio is playing
    playlistUtils.audio.onplay = function () {
        $('#wait').remove();
    }
})
<|endoftext|>


<commit_before>var defaultApp = 'contactsviewer';
var specialApps = {
    "connect" : "connect"
    "allApps"  : "allApps",
    "connect"  : "connect",
    "settings" : "settings"
};
var defaultSubSections = {};
var loggedIn = true;

$(document).ready(function() {
  $.history.init(function(hash){
    loadDiv(window.location.hash.substring(1) || $('.installed-apps a').data('id') || '#Explore-' + defaultApp);
  }, { unescape: ",/" });

  $('body').delegate('.install', 'click', function(e) {
    var $e = $(e.currentTarget);
    var id = $e.attr('id');
    $.get('/registry/add/' + id, function() {
      window.location = 'explore#Explore-' + id;
    });
    return false;
  });

  $('body').delegate('.oauthLink','click', function(e) {
    var options = "width=" + $(this).data('width') + ",height=" + $(this).data('height') + ",status=no,scrollbars=no,resizable=no";
    var popup = window.open($(this).attr('href'), "account", options);
    popup.focus();
    return false;
  });

  $('.your-apps').click(function() {
    $('.blue').removeClass('blue');
    $(this).addClass('blue');
    if (document.getElementById('appFrame').contentWindow.filterItems) {
      document.getElementById('appFrame').contentWindow.filterItems($(this).attr('id'));
    }
  });

  var modalClosed = true;
  function doModal(sectionNum) {
    if (!modalClosed) return;
    modalClosed = false;
    var modal = $('#basic-modal-content').modal({onClose: function (dialog) {
      modalClosed = true;
      $.modal.close();
    }});
    $('#simplemodal-overlay,#no-thanks,#close-button,#close-this,.gotit-button').click(function(e) {
      $.cookie("firstvisit", null, {path: '/' });
      modal.close();
    });
  }

  if (window.location.hash !== '#Explore-connect' && $.cookie("firstvisit") === 'true') {
      if (window.location.hash === '#Develop-devdocs' || window.location.hash === '#AppGallery-Featured') {
        $.cookie("firstvisit", null, {path: '/' });
      } else {
        doModal();
      }
  }
});

var loadApp = function(info) {
  var app = info.subSection || info.topSection;
  $('.app-container').hide();
  $('.app-container#iframeContainer').show();
  $('.app-details').hide();
  if (specialApps[app]) {
    $("#appFrame")[0].contentWindow.location.replace(specialApps[app] + '?params=' + info.params);
  } else if (info.topSection === "Settings") {
    if (info.subSection === "Connections") {
      $("#appFrame")[0].contentWindow.location.replace('/Dashboard/settings-connectors');
    } else if (info.subSection === "AccountInformation") {
      $("#appFrame")[0].contentWindow.location.replace('/Dashboard/settings-account');
    } else if (info.subSection === "APIKey") {
      $("#appFrame")[0].contentWindow.location.replace('/Dashboard/settings-api');
    } else {
      alert("CAN YOOOOO SMELL WHAT THE ROCK IS COOOKING?");
    }
  } else if (app === "Publish") {
    $("#appFrame")[0].contentWindow.location.replace('publish?app=' + info.params.app);
    $('#appHeader').hide();
  } else if (app === "connect") {
    $("#appFrame")[0].contentWindow.location.replace('/Dashboard/connect');
  } else {
    handleApp(app);
  }

  $('.iframeLink[data-id="' + info.app + '"]').parent('p').siblings().show();
};

var syncletInstalled = function(provider) {
  if (provider === 'github') {
    $('.your-apps').show();
  }
  var link = $('.sidenav .oauthLink[data-provider="' + provider + '"]');
  if($('#appDiv').is(':visible')) {
    link.each(function(index, element) {
      element = $(element);
      var nxt = element.next('span');
      if(!nxt.length) nxt = element.prev('span');
      nxt.remove();
      element.remove();
    });
  } else {
    var connectedList = $('.sidenav-items.synclets-connected');
    // \n's are for spacing, gross, but true
    connectedList.append('\n\n\n').append(link.find('img'));
    link.remove();
  }
  link = $('#appHeader .unconnected-services .oauthLink[data-provider="' + provider + '"]');
  if(link.length) {
    var unConnectedList = $('#appHeader .connected-services');
    // \n's are for spacing, gross, but true
    unConnectedList.append('\n\n\n').append(link.find('img').addClass('installed'));
    link.remove();
  }
};

handlers.Explore = loadApp;
handlers.Develop = loadApp;
handlers.connect = loadApp;
handlers.Settings = loadApp;
handlers.viewAll = loadApp;
handlers.publish = loadApp;

function handleApp(appName) {
  $.get('clickapp/' + appName, function(e) {});
  doAppHeader(appName);
  $("#appFrame")[0].contentWindow.location.replace('/Me/' + appName);
}

function doAppHeader(appName) {
  registry.getMap(function(err, map) {
    if(err || !map[appName]) return callback(err, map);
    var app = map[appName];
    // this {repository: app} stuff is because the map flattens the things in the repository field
    // up to the top level, but these registry functions expect them to be inside of repository
    registry.getConnectedServices({repository: app}, function(connected) {
      registry.getUnConnectedServices({repository: app}, function(unconnected) {
        registry.getMyAuthoredApps(function(myAuthoredApps) {
          var mine = myAuthoredApps[appName];
          if (mine) app.author = registry.localAuthor;
          dust.render('appHeader', {app:app, connected:connected, unconnected:unconnected, mine:mine}, function(err, appHtml) {
            $('#appHeader').html(appHtml);
            $('#appHeader').show();
          });
        });
      });
    });
  });
}
<commit_msg>typo fix<commit_after>var defaultApp = 'contactsviewer';
var specialApps = {
    "connect" : "connect",
    "allApps"  : "allApps",
    "connect"  : "connect",
    "settings" : "settings"
};
var defaultSubSections = {};
var loggedIn = true;

$(document).ready(function() {
  $.history.init(function(hash){
    loadDiv(window.location.hash.substring(1) || $('.installed-apps a').data('id') || '#Explore-' + defaultApp);
  }, { unescape: ",/" });

  $('body').delegate('.install', 'click', function(e) {
    var $e = $(e.currentTarget);
    var id = $e.attr('id');
    $.get('/registry/add/' + id, function() {
      window.location = 'explore#Explore-' + id;
    });
    return false;
  });

  $('body').delegate('.oauthLink','click', function(e) {
    var options = "width=" + $(this).data('width') + ",height=" + $(this).data('height') + ",status=no,scrollbars=no,resizable=no";
    var popup = window.open($(this).attr('href'), "account", options);
    popup.focus();
    return false;
  });

  $('.your-apps').click(function() {
    $('.blue').removeClass('blue');
    $(this).addClass('blue');
    if (document.getElementById('appFrame').contentWindow.filterItems) {
      document.getElementById('appFrame').contentWindow.filterItems($(this).attr('id'));
    }
  });

  var modalClosed = true;
  function doModal(sectionNum) {
    if (!modalClosed) return;
    modalClosed = false;
    var modal = $('#basic-modal-content').modal({onClose: function (dialog) {
      modalClosed = true;
      $.modal.close();
    }});
    $('#simplemodal-overlay,#no-thanks,#close-button,#close-this,.gotit-button').click(function(e) {
      $.cookie("firstvisit", null, {path: '/' });
      modal.close();
    });
  }

  if (window.location.hash !== '#Explore-connect' && $.cookie("firstvisit") === 'true') {
      if (window.location.hash === '#Develop-devdocs' || window.location.hash === '#AppGallery-Featured') {
        $.cookie("firstvisit", null, {path: '/' });
      } else {
        doModal();
      }
  }
});

var loadApp = function(info) {
  var app = info.subSection || info.topSection;
  $('.app-container').hide();
  $('.app-container#iframeContainer').show();
  $('.app-details').hide();
  if (specialApps[app]) {
    $("#appFrame")[0].contentWindow.location.replace(specialApps[app] + '?params=' + info.params);
  } else if (info.topSection === "Settings") {
    if (info.subSection === "Connections") {
      $("#appFrame")[0].contentWindow.location.replace('/Dashboard/settings-connectors');
    } else if (info.subSection === "AccountInformation") {
      $("#appFrame")[0].contentWindow.location.replace('/Dashboard/settings-account');
    } else if (info.subSection === "APIKey") {
      $("#appFrame")[0].contentWindow.location.replace('/Dashboard/settings-api');
    } else {
      alert("CAN YOOOOO SMELL WHAT THE ROCK IS COOOKING?");
    }
  } else if (app === "Publish") {
    $("#appFrame")[0].contentWindow.location.replace('publish?app=' + info.params.app);
    $('#appHeader').hide();
  } else if (app === "connect") {
    $("#appFrame")[0].contentWindow.location.replace('/Dashboard/connect');
  } else {
    handleApp(app);
  }

  $('.iframeLink[data-id="' + info.app + '"]').parent('p').siblings().show();
};

var syncletInstalled = function(provider) {
  if (provider === 'github') {
    $('.your-apps').show();
  }
  var link = $('.sidenav .oauthLink[data-provider="' + provider + '"]');
  if($('#appDiv').is(':visible')) {
    link.each(function(index, element) {
      element = $(element);
      var nxt = element.next('span');
      if(!nxt.length) nxt = element.prev('span');
      nxt.remove();
      element.remove();
    });
  } else {
    var connectedList = $('.sidenav-items.synclets-connected');
    // \n's are for spacing, gross, but true
    connectedList.append('\n\n\n').append(link.find('img'));
    link.remove();
  }
  link = $('#appHeader .unconnected-services .oauthLink[data-provider="' + provider + '"]');
  if(link.length) {
    var unConnectedList = $('#appHeader .connected-services');
    // \n's are for spacing, gross, but true
    unConnectedList.append('\n\n\n').append(link.find('img').addClass('installed'));
    link.remove();
  }
};

handlers.Explore = loadApp;
handlers.Develop = loadApp;
handlers.connect = loadApp;
handlers.Settings = loadApp;
handlers.viewAll = loadApp;
handlers.publish = loadApp;

function handleApp(appName) {
  $.get('clickapp/' + appName, function(e) {});
  doAppHeader(appName);
  $("#appFrame")[0].contentWindow.location.replace('/Me/' + appName);
}

function doAppHeader(appName) {
  registry.getMap(function(err, map) {
    if(err || !map[appName]) return callback(err, map);
    var app = map[appName];
    // this {repository: app} stuff is because the map flattens the things in the repository field
    // up to the top level, but these registry functions expect them to be inside of repository
    registry.getConnectedServices({repository: app}, function(connected) {
      registry.getUnConnectedServices({repository: app}, function(unconnected) {
        registry.getMyAuthoredApps(function(myAuthoredApps) {
          var mine = myAuthoredApps[appName];
          if (mine) app.author = registry.localAuthor;
          dust.render('appHeader', {app:app, connected:connected, unconnected:unconnected, mine:mine}, function(err, appHtml) {
            $('#appHeader').html(appHtml);
            $('#appHeader').show();
          });
        });
      });
    });
  });
}
<|endoftext|>


<commit_before>/*
 * class Logger
 */

var _lastId = null;

module.exports = function Logger(id) {

    var LINE_FORMAT = "%s%d-%02d-%02d %02d:%02d:%02d.%0-3d - %s",
    Level = {
        OFF		: (-1 >>> 1),
        SEVERE	: 1000,
        WARNING	: 900,
        INFO	: 800,
        DEBUG	: 700,
        CONFIG	: 650,
        STATUS	: 600,
        FINE	: 500,
        FINER	: 400,
        FINEST	: 300,
        ALL		: -((-1 >>> 1)+1)
    };
    for(var key in Level)
        Level[Level[key]] = key;

    var actLevel = Level.INFO,
        slaves = {}, slave_id = 1;

    return {
        Level: Level,

        log: log,
        error: error,

        severe:	function() { _log(Level.SEVERE, arguments); },
        warning:function() { _log(Level.WARNING, arguments); },
        info:	function() { _log(Level.INFO, arguments); },
        status:	function() { _log(Level.STATUS, arguments); },
        debug:	function() { _log(Level.DEBUG, arguments); },
        config:	function() { _log(Level.CONFIG, arguments); },
        fine:	function() { _log(Level.FINE, arguments); },
        finer:	function() { _log(Level.FINER, arguments); },
        finest:	function() { _log(Level.FINEST, arguments); },

        level: function(level) { if(level) actLevel = level; return actLevel; },
        isLoggable : isLoggable,

        addSlave: addSlave,
        removeSlave: removeSlave
    };

    function isLoggable(level) {
        if(typeof level === 'string')
            level = Level[level]
        return (level >= actLevel);
    }

    function addSlave(slave) {
        if(!slave.log)
            throw new Error("not logger slave!");

        if(!slave.id)
            slave.id = "ls-"+slave_id++;
        slaves[slave.id] = slave;
    }

    function removeSlave(slave) {
        if(slave.id && slaves[slave.id])
            delete slaves[slave.id];
    }

    function log() {

        // allways call the slaves and let them decide
        for(var id in slaves)
            slaves[id].log.apply(slaves[id], arguments);

        var level = parseInt(arguments[0]);

        if(level >= actLevel && level < Level.OFF) {

            if(console)
                _console.apply(this, arguments);
        }
    }

    function error() {
        for(var i=0; i<arguments.length; i++) {
            if( !((err = arguments[i]) instanceof Error) ) {
                try {throw new Error(err.message)} catch(e) {err=e}
            }
            _log(Level.SEVERE, [err]);
        }
    }

    function _log(level, args) {
        Array.prototype.unshift.call(args, parseInt(level));
        log.apply(this, args);
    }

    function _console() {

        var date = new Date(),
            level = Level[Array.prototype.shift.call(arguments)];

        var method;
        switch(level) {
            case "SEVERE" : method = "error"; break;
            case "WARNING" : method = "warn"; break;
            case "INFO" : method = "info"; break;
            default : method = "log"; break;
        }

        var _lf = _lastId ? '\n' : ''
        arguments[0] = floyd.tools.strings.sprintf(LINE_FORMAT,
            ((_lastId != id && (_lastId = id)) ? _lf+id+'\n' : ''),
            date.getFullYear(), date.getMonth()+1, date.getDate(),
            date.getHours(), date.getMinutes(), date.getSeconds(),
            date.getMilliseconds(), arguments[0])

            if(console[method].apply) {
            	console[method].apply(console, arguments);
            } else {
            	console[method](Array.prototype.slice.apply(arguments).join(' '));
            }

    }
};
<commit_msg>added ability to publish log entries<commit_after>/*
 * class Logger
 */

var _lastId = null;

module.exports = function Logger(id) {

    var LINE_FORMAT = "%s%d-%02d-%02d %02d:%02d:%02d.%0-3d - %s",
    Level = {
        OFF		: (-1 >>> 1),
        SEVERE	: 1000,
        WARNING	: 900,
        INFO	: 800,
        DEBUG	: 700,
        CONFIG	: 650,
        STATUS	: 600,
        FINE	: 500,
        FINER	: 400,
        FINEST	: 300,
        ALL		: -((-1 >>> 1)+1)
    };
    for(var key in Level)
        Level[Level[key]] = key;

    var actLevel = Level.INFO,
        slaves = {}, slave_id = 1;

    var api;
    return api = {
        Level: Level,

        log: log,
        error: error,

        severe:	function() { _log(Level.SEVERE, arguments); },
        warning:function() { _log(Level.WARNING, arguments); },
        info:	function() { _log(Level.INFO, arguments); },
        status:	function() { _log(Level.STATUS, arguments); },
        debug:	function() { _log(Level.DEBUG, arguments); },
        config:	function() { _log(Level.CONFIG, arguments); },
        fine:	function() { _log(Level.FINE, arguments); },
        finer:	function() { _log(Level.FINER, arguments); },
        finest:	function() { _log(Level.FINEST, arguments); },

        level: function(level) { if(level) actLevel = level; return actLevel; },
        isLoggable : isLoggable,

        addSlave: addSlave,
        removeSlave: removeSlave,

        _console: _console
    };

    function isLoggable(level) {
        if(typeof level === 'string')
            level = Level[level]
        return (level >= actLevel && level < Level.OFF);
    }

    function addSlave(slave) {
        if(!slave.log)
            throw new Error("not logger slave!");

        if(!slave.id)
            slave.id = "ls-"+slave_id++;
        slaves[slave.id] = slave;
    }

    function removeSlave(slave) {
        if(slave.id && slaves[slave.id])
            delete slaves[slave.id];
    }

    function log() {

        // allways call the slaves and let them decide
        for(var sid in slaves)
            slaves[sid].log.apply(slaves[sid], arguments);

        level = arguments[0]

        if(isLoggable(level)) {
            Array.prototype.unshift.call(arguments, new Date());
            Array.prototype.unshift.call(arguments, id);

            if(api.publish) {
                api.publish(arguments)
            } else {
                _console.apply(this, arguments);
            }
        }

    }

    function error() {
        for(var i=0; i<arguments.length; i++) {
            if( !((err = arguments[i]) instanceof Error) ) {
                try {throw new Error(err.message)} catch(e) {err=e}
            }
            _log(Level.SEVERE, [err]);
        }
    }

    function _log(level, args) {
        Array.prototype.unshift.call(args, parseInt(level));
        log.apply(this, args);
    }

    function _console() {
        var _id = Array.prototype.shift.call(arguments);
        var date = Array.prototype.shift.call(arguments);
        var level = Array.prototype.shift.call(arguments);
        var method;
        switch(level) {
            case "SEVERE" : method = "error"; break;
            case "WARNING" : method = "warn"; break;
            case "INFO" : method = "info"; break;
            default : method = "log"; break;
        }

        var _lf = _lastId ? '\n' : ''
        arguments[0] = floyd.tools.strings.sprintf(LINE_FORMAT,
            ((_lastId != _id && (_lastId = _id)) ? _lf+_id+'\n' : ''),
            date.getFullYear(), date.getMonth()+1, date.getDate(),
            date.getHours(), date.getMinutes(), date.getSeconds(),
            date.getMilliseconds(), arguments[0])

        if(api.console) {
            api.console(arguments)

        } else if(api.console != false && console) {
            if(console[method].apply) {
                console[method].apply(console, arguments);
            } else {
                console[method](Array.prototype.slice.apply(arguments).join(' '));
            }
        }
    }

};
<|endoftext|>


<commit_before>module.exports = function(app) {
  var Role = app.models.Role;

   Role.registerResolver('teamMember', function(role, context, cb) {

    function reject(msg) {
      console.log(msg);
      process.nextTick(function() {
      cb(null, false);
      });
    }

    var userId = context.accessToken.userId;
      console.log(context.accessToken);
      if (!userId) {
      return reject("Invalid access token");
    }

    cb(null, true);

   });
};<commit_msg>Implement basic role for accounts<commit_after>module.exports = function(app) {
  var Role = app.models.Role;

   Role.registerResolver('teamMember', function(role, context, cb) {

    function reject(msg) {
      console.log(msg);
      process.nextTick(function() {
      cb(null, false);
      });
    }

    var userId = context.accessToken.userId;
      if (!userId) {
      return reject('Invalid access token');
    }

    context.model.findById(context.modelId, function provideModel(err, model) {
      if (err || !model) { return reject('No relative model found.');}

      model.users.findById(userId, function postFind(err, users) {
        if (err || !users) {
          reject("Unauthorized!");
        } else {
          cb(null, true);
        }

      });
    });

   });
};
<|endoftext|>


<commit_before>var Tinkerforge = require('tinkerforge');

var LIGHT,
  BARO,
  HUMI,
  al,
  h,
  b,
  ipcon,
  Humidity,
  AirPressure,
  Temperature,
  Illuminance;
/* istanbul ignore next */
function ipcon_connect(HOST, PORT) {
  ipcon.connect(HOST, PORT,
    function(error) {
      switch (error) {
        case 11:
          console.log('Error: ALREADY CONNECTED');
          break;
        case 12:
          console.log('Error: NOT CONNECTED');
          break;
        case 13:
          console.log('Error: CONNECT FAILED');
          break;
        case 21:
          console.log('Error: INVALID FUNCTION ID');
          break;
        case 31:
          console.log('Error: TIMEOUT');
          break;
        case 41:
          console.log('Error: INVALID PARAMETER');
          break;
        case 42:
          console.log('Error: FUNCTION NOT SUPPORTED');
          break;
        default:
          console.log('Error: UNKNOWN ERROR');
          break;
      }
      process.exit();
    }
  );
}
/* istanbul ignore next */
function get_uid(HOST, PORT) {
  ipcon = new Tinkerforge.IPConnection();
  ipcon_connect(HOST, PORT);
  ipcon.on(Tinkerforge.IPConnection.CALLBACK_CONNECTED,
    function(connectReason) {
      ipcon.enumerate();
    }
  );
  ipcon.on(Tinkerforge.IPConnection.CALLBACK_ENUMERATE,
    function(uid, connectedUid, position, hardwareVersion, firmwareVersion, deviceIdentifier) {
      if (deviceIdentifier === Tinkerforge.BrickletAmbientLight.DEVICE_IDENTIFIER) {
        LIGHT = uid;
      } else if (deviceIdentifier === Tinkerforge.BrickletBarometer.DEVICE_IDENTIFIER) {
        BARO = uid;
      } else if (deviceIdentifier === Tinkerforge.BrickletHumidity.DEVICE_IDENTIFIER) {
        HUMI = uid;
      }
    }
  );
}
/* istanbul ignore next */
function tfinit(HOST, PORT) {
  ipcon = new Tinkerforge.IPConnection();
  al = new Tinkerforge.BrickletAmbientLight(LIGHT, ipcon);
  b = new Tinkerforge.BrickletBarometer(BARO, ipcon);
  h = new Tinkerforge.BrickletHumidity(HUMI, ipcon);
  ipcon_connect(HOST, PORT);
}
/* istanbul ignore next */
function tfdata_get() {
  h.getHumidity(
    function(humidity) {
      Humidity = humidity / 10 + ' %RH';
    },
    function(error) {
      Humidity = 'Error ' + error;
    }
  );
  b.getAirPressure(
    function(air_pressure) {
      AirPressure = air_pressure / 1000 + ' mbar';
    },
    function(error) {
      AirPressure = 'Error ' + error;
    }
  );
  b.getChipTemperature(
    function(temperature) {
      Temperature = temperature / 100 + ' \u00B0C';
    },
    function(error) {
      Temperature = 'Error ' + error;
    }
  );
  al.getIlluminance(
    function(illuminance) {
      Illuminance = illuminance / 10 + ' Lux';
    },
    function(error) {
      Illuminance = 'Error ' + error;
    }
  );
}
/* istanbul ignore next */
function getTime(date) {
  return ((date.getHours() < 10 ? "0" : "") + date.getHours()) + ":" + ((date.getMinutes() < 10 ? "0" : "") + date.getMinutes()) + ":" + ((date.getSeconds() < 10 ? "0" : "") + date.getSeconds());
}
/* istanbul ignore next */
exports.get = function tfget(HOST, PORT, WAIT, live) {
  get_uid(HOST, PORT);
  if (live === true) {
    setTimeout(function() {
      setTimeout(function() {
        ipcon.disconnect();
        tfinit(HOST, PORT);
      }, 250);
      setTimeout(function() {
        process.stdin.on('data',
          function(data) {
            ipcon.disconnect();
            process.exit();
          }
        );
        tfdata_get();
        setInterval(function() {
          console.log('\033[2J');
          console.log('Relative Humidity: ' + Humidity);
          console.log('Air pressure:      ' + AirPressure);
          console.log('Temperature:       ' + Temperature);
          console.log('Illuminance:       ' + Illuminance);
          console.log('\nTime:              ' + getTime(new Date()));
          tfdata_get();
        }, WAIT);
      }, 300);
    }, 250);
  } else {
    setTimeout(function() {
      tfinit(HOST, PORT);
      ipcon.on(Tinkerforge.IPConnection.CALLBACK_CONNECTED,
        function(connectReason) {
          tfdata_get();
        }
      );
      setTimeout(function() {
        console.log('');
        console.log('Relative Humidity: ' + Humidity);
        console.log('Air pressure:      ' + AirPressure);
        console.log('Temperature:       ' + Temperature);
        console.log('Illuminance:       ' + Illuminance);
        console.log('\nTime:              ' + getTime(new Date()));
        console.log('');
        ipcon.disconnect();
        process.exit(0);
      }, 25);
    }, 50);
  }
};
<commit_msg>better usability<commit_after>var Tinkerforge = require('tinkerforge');

var LIGHT,
  BARO,
  HUMI,
  al,
  h,
  b,
  ipcon,
  Humidity,
  AirPressure,
  Temperature,
  Illuminance;
/* istanbul ignore next */
function ipcon_connect(HOST, PORT) {
  ipcon.connect(HOST, PORT,
    function(error) {
      switch (error) {
        case 11:
          console.log('Error: ALREADY CONNECTED');
          break;
        case 12:
          console.log('Error: NOT CONNECTED');
          break;
        case 13:
          console.log('Error: CONNECT FAILED');
          break;
        case 21:
          console.log('Error: INVALID FUNCTION ID');
          break;
        case 31:
          console.log('Error: TIMEOUT');
          break;
        case 41:
          console.log('Error: INVALID PARAMETER');
          break;
        case 42:
          console.log('Error: FUNCTION NOT SUPPORTED');
          break;
        default:
          console.log('Error: UNKNOWN ERROR');
          break;
      }
      process.exit();
    }
  );
}
/* istanbul ignore next */
function get_uid(HOST, PORT) {
  ipcon = new Tinkerforge.IPConnection();
  ipcon_connect(HOST, PORT);
  ipcon.on(Tinkerforge.IPConnection.CALLBACK_CONNECTED,
    function(connectReason) {
      ipcon.enumerate();
    }
  );
  ipcon.on(Tinkerforge.IPConnection.CALLBACK_ENUMERATE,
    function(uid, connectedUid, position, hardwareVersion, firmwareVersion, deviceIdentifier) {
      if (deviceIdentifier === Tinkerforge.BrickletAmbientLight.DEVICE_IDENTIFIER) {
        LIGHT = uid;
      } else if (deviceIdentifier === Tinkerforge.BrickletBarometer.DEVICE_IDENTIFIER) {
        BARO = uid;
      } else if (deviceIdentifier === Tinkerforge.BrickletHumidity.DEVICE_IDENTIFIER) {
        HUMI = uid;
      }
    }
  );
}
/* istanbul ignore next */
function tfinit(HOST, PORT) {
  ipcon = new Tinkerforge.IPConnection();
  al = new Tinkerforge.BrickletAmbientLight(LIGHT, ipcon);
  b = new Tinkerforge.BrickletBarometer(BARO, ipcon);
  h = new Tinkerforge.BrickletHumidity(HUMI, ipcon);
  ipcon_connect(HOST, PORT);
}
/* istanbul ignore next */
function tfdata_get() {
  h.getHumidity(
    function(humidity) {
      Humidity = humidity / 10 + ' %RH';
    },
    function(error) {
      Humidity = 'Error ' + error;
    }
  );
  b.getAirPressure(
    function(air_pressure) {
      AirPressure = air_pressure / 1000 + ' mbar';
    },
    function(error) {
      AirPressure = 'Error ' + error;
    }
  );
  b.getChipTemperature(
    function(temperature) {
      Temperature = temperature / 100 + ' \u00B0C';
    },
    function(error) {
      Temperature = 'Error ' + error;
    }
  );
  al.getIlluminance(
    function(illuminance) {
      Illuminance = illuminance / 10 + ' Lux';
    },
    function(error) {
      Illuminance = 'Error ' + error;
    }
  );
}
/* istanbul ignore next */
function getTime(date) {
  return ((date.getHours() < 10 ? "0" : "") + date.getHours()) + ":" + ((date.getMinutes() < 10 ? "0" : "") + date.getMinutes()) + ":" + ((date.getSeconds() < 10 ? "0" : "") + date.getSeconds());
}
/* istanbul ignore next */
function output() {
  console.log('Relative Humidity: ' + Humidity);
  console.log('Air pressure:      ' + AirPressure);
  console.log('Temperature:       ' + Temperature);
  console.log('Illuminance:       ' + Illuminance);
  console.log('\nTime:              ' + getTime(new Date()));
}
/* istanbul ignore next */
exports.get = function tfget(HOST, PORT, WAIT, live) {
  get_uid(HOST, PORT);
  if (live === true) {
    setTimeout(function() {
      setTimeout(function() {
        ipcon.disconnect();
        tfinit(HOST, PORT);
      }, 250);
      setTimeout(function() {
        process.stdin.on('data',
          function(data) {
            ipcon.disconnect();
            process.exit();
          }
        );
        tfdata_get();
        setInterval(function() {
          tfdata_get();
          console.log('\033[2J');
          output();
        }, WAIT);
      }, 300);
    }, 250);
  } else {
    setTimeout(function() {
      tfinit(HOST, PORT);
      ipcon.on(Tinkerforge.IPConnection.CALLBACK_CONNECTED,
        function(connectReason) {
          tfdata_get();
        }
      );
      setTimeout(function() {
        console.log('');
        output();
        console.log('');
        ipcon.disconnect();
        process.exit(0);
      }, 25);
    }, 50);
  }
};
<|endoftext|>


<commit_before>var _ = require('underscore');
var async = require('async');
var fs = require('fs');
var path = require('path');
var yaml = require('js-yaml');
var coffee = require('coffee-script');
var url = require('url');
var koa = require('koa');
var mount = require('koa-mount');
var serve = require('koa-static');
var route = require('koa-route');

var doctrine = require('doctrine');
var descriptor = {};
var resources = {};

/**
 * Read from yml file
 * @api    private
 * @param  {String}   file
 * @param  {Function} fn
 */
function readYml(file, fn) {
  var resource = require(path.resolve(process.cwd(), file));
  var api = {};

  api.resourcePath = resource.resourcePath;
  api.description = resource.description;
  descriptor.apis.push(api);
  resources[resource.resourcePath] = resource;

  fn();
}

/**
 * Parse jsDoc from a js file
 * @api    private
 * @param  {String}   file
 * @param  {Function} fn
 */
function parseJsDocs(file, fn) {
  fs.readFile(file, function(err, data) {
    if (err) {
      fn(err);
    }

    var js = data.toString();
    var regex = /\/\*\*([\s\S]*?)\*\//gm;
    var fragments = js.match(regex);
    var docs = [];

    if (!fragments) {
      fn(null, docs);
      return;
    }

    for (var i = 0; i < fragments.length; i++) {
      var fragment = fragments[i];
      var doc = doctrine.parse(fragment, {unwrap: true});

      docs.push(doc);

      if (i === fragments.length - 1) {
        fn(null, docs);
      }
    }
  });
}

/**
 * Parse coffeeDoc from a coffee file
 * @api    private
 * @param  {String}   file
 * @param  {Function} fn
 */
function parseCoffeeDocs(file, fn) {
  fs.readFile(file, function(err, data) {
    if (err) {
      fn(err);
    }

    var js = coffee.compile(data.toString());
    var regex = /\/\**([\s\S]*?)\*\//gm;
    var fragments = js.match(regex);
    var docs = [];

    for (var i = 0; i < fragments.length; i++) {
      var fragment = fragments[i];
      var doc = doctrine.parse(fragment, {unwrap: true});

      docs.push(doc);

      if (i === fragments.length - 1) {
        fn(null, docs);
      }
    }
  });
}

/**
 * Get jsDoc tag with title '@swagger'
 * @api    private
 * @param  {Object} fragment
 * @param  {Function} fn
 */
function getSwagger(fragment, fn) {
  for (var i = 0; i < fragment.tags.length; i++) {
    var tag = fragment.tags[i];
    if ('swagger' === tag.title) {
      return yaml.safeLoadAll(tag.description, fn);
    }
  }

  return fn(false);
}

/**
 *
 * @param {Object} api
 */
function pushApiIfDoesNotExist(api) {
  var found = _.findWhere(descriptor.apis, {resourcePath: api.resourcePath});

  if (found) {
    return;
  }

  descriptor.apis.push(api);
}

/**
 *
 * @param {Function} fn
 * @returns {Function}
 */
function createParserCb(fn) {
  return function(err, docs) {

    if (err) {
      fn(err);
    }

    var resource = {apis: []};

    async.eachSeries(docs, function(doc, cb) {
      getSwagger(doc, function(api) {

        if (!api) {
          return cb();
        }

        // do not rewrite existing resource
        if (resources[api.resourcePath]) {
          resource = resources[api.resourcePath];
        }

        if (api.resourcePath) {
          pushApiIfDoesNotExist(api);
          resource.resourcePath = api.resourcePath;
        } else if (api.models) {
          resource.models = Object.assign({}, resource.models || {}, api.models);
        } else {
          resource.apis.push(api);
        }

        cb();
      });
    }, function() {
      if (resource.resourcePath){
        resources[resource.resourcePath] = resource;
      }
      fn();
    });
  };
}

/**
 * Read from jsDoc
 * @api    private
 * @param  {String}  file
 * @param  {Function} fn
 */
function readJsDoc(file, fn) {
  parseJsDocs(file, createParserCb(fn));
}

/**
 * Read from coffeeDoc
 * @api    private
 * @param  {String}  file
 * @param  {Function} fn
 */
function readCoffee(file, fn) {
  parseCoffeeDocs(file, createParserCb(fn));
}

/**
 * Read API from file
 * @api    private
 * @param  {String}   file
 * @param  {Function} fn
 */
function readApi(file, fn) {
  var ext = path.extname(file);
  if ('.js' === ext) {
    readJsDoc(file, fn);
  } else if ('.yml' === ext) {
    readYml(file, fn);
  } else if ('.coffee' === ext) {
    readCoffee(file, fn);
  } else {
    throw new Error('Unsupported extension \'' + ext + '\'');
  }
}

/**
 * Generate Swagger documents
 * @api    private
 * @param  {Object} opt
 */
function generate(opt) {
  if (!opt) {
    throw new Error('\'option\' is required.');
  }

  if (!opt.swaggerUI) {
    throw new Error('\'swaggerUI\' is required.');
  }

  if (!opt.basePath) {
    throw new Error('\'basePath\' is required.');
  }

  descriptor.basePath = opt.basePath;
  descriptor.apiVersion = (opt.apiVersion) ? opt.apiVersion : '1.0';
  descriptor.swaggerVersion = (opt.swaggerVersion) ? opt.swaggerVersion : '1.0';
  descriptor.swaggerURL = (opt.swaggerURL) ? opt.swaggerURL : '/swagger';
  descriptor.swaggerJSON = (opt.swaggerJSON) ? opt.swaggerJSON : '/api-docs.json';
  descriptor.apis = [];

  if (opt.info) {
    descriptor.info = opt.info;
  }

  opt.apiVersion = descriptor.apiVersion;
  opt.swaggerVersion = descriptor.swaggerVersion;
  opt.swaggerURL = descriptor.swaggerURL;
  opt.swaggerJSON = descriptor.swaggerJSON;

  if (!opt.fullSwaggerJSONPath) {
    opt.fullSwaggerJSONPath = url.parse(opt.basePath + opt.swaggerJSON).path;
  }

  if (opt.apis) {
    opt.apis.forEach(function(api) {
      readApi(api, function(err) {
        if (err) {
          throw err;
        }
      });
    });
  }
}

/**
 * Koa middleware
 * @api    public
 * @param  {Object} app
 * @param  {Object} opt
 * @return {Function}
 */
exports.init = function(opt) {
  // generate resources
  generate(opt);

  var app = koa();

  app.use(function *(next) {
    if (this.path === opt.swaggerURL) { // koa static barfs on root url w/o trailing slash
      this.redirect(this.path + '/');
    } else {
      yield next;
    }
  });

  app.use(mount(opt.swaggerURL, serve(opt.swaggerUI)));

  var swaggerJSON = function *(resourceName) {
    var result = _.clone(descriptor);

    if (resourceName) {
      if (resourceName==opt.singlePagePath){
        result = {}

        Object.keys(resources).forEach((name)=>{
          var resource = resources[name]
          for(var attribute in resource){
            if (Array.isArray(resource[attribute])){
              //arrays
              result[attribute] = result[attribute] || [];
              result[attribute] = result[attribute].concat(resource[attribute])
            }else if (typeof(resource[attribute])=='object'){
              // objects
              result[attribute] = result[attribute] || {};
              result[attribute] = Object.assign(result[attribute],resource[attribute])
            }else{
              // primatives (Strings / Numbers etc')
              result[attribute] = result[attribute] || [];
              result[attribute].push(resource[attribute])
            }

          }
        });

      }else{
        var resource = resources['/' + resourceName];

        if (!resource) {
          this.status = 404;
          return;
        }

        result.resourcePath = resource.resourcePath;
        result.apis = resource.apis;
        result.models = resource.models;
      }
    } else {

        result.apis = _.map(result.apis, function(api) {
          return {
            path: opt.swaggerJSON + api.resourcePath,
            description: api.description
          };
        });
    }

    this.body = result;
  };

  app.use(route.get(opt.fullSwaggerJSONPath + '/:resourceName*', swaggerJSON));

  return mount(app, '/');
};

exports.descriptor = descriptor;
exports.resources = resources;
<commit_msg>fixed output format<commit_after>var _ = require('underscore');
var async = require('async');
var fs = require('fs');
var path = require('path');
var yaml = require('js-yaml');
var coffee = require('coffee-script');
var url = require('url');
var koa = require('koa');
var mount = require('koa-mount');
var serve = require('koa-static');
var route = require('koa-route');

var doctrine = require('doctrine');
var descriptor = {};
var resources = {};

/**
 * Read from yml file
 * @api    private
 * @param  {String}   file
 * @param  {Function} fn
 */
function readYml(file, fn) {
  var resource = require(path.resolve(process.cwd(), file));
  var api = {};

  api.resourcePath = resource.resourcePath;
  api.description = resource.description;
  descriptor.apis.push(api);
  resources[resource.resourcePath] = resource;

  fn();
}

/**
 * Parse jsDoc from a js file
 * @api    private
 * @param  {String}   file
 * @param  {Function} fn
 */
function parseJsDocs(file, fn) {
  fs.readFile(file, function(err, data) {
    if (err) {
      fn(err);
    }

    var js = data.toString();
    var regex = /\/\*\*([\s\S]*?)\*\//gm;
    var fragments = js.match(regex);
    var docs = [];

    if (!fragments) {
      fn(null, docs);
      return;
    }

    for (var i = 0; i < fragments.length; i++) {
      var fragment = fragments[i];
      var doc = doctrine.parse(fragment, {unwrap: true});

      docs.push(doc);

      if (i === fragments.length - 1) {
        fn(null, docs);
      }
    }
  });
}

/**
 * Parse coffeeDoc from a coffee file
 * @api    private
 * @param  {String}   file
 * @param  {Function} fn
 */
function parseCoffeeDocs(file, fn) {
  fs.readFile(file, function(err, data) {
    if (err) {
      fn(err);
    }

    var js = coffee.compile(data.toString());
    var regex = /\/\**([\s\S]*?)\*\//gm;
    var fragments = js.match(regex);
    var docs = [];

    for (var i = 0; i < fragments.length; i++) {
      var fragment = fragments[i];
      var doc = doctrine.parse(fragment, {unwrap: true});

      docs.push(doc);

      if (i === fragments.length - 1) {
        fn(null, docs);
      }
    }
  });
}

/**
 * Get jsDoc tag with title '@swagger'
 * @api    private
 * @param  {Object} fragment
 * @param  {Function} fn
 */
function getSwagger(fragment, fn) {
  for (var i = 0; i < fragment.tags.length; i++) {
    var tag = fragment.tags[i];
    if ('swagger' === tag.title) {
      return yaml.safeLoadAll(tag.description, fn);
    }
  }

  return fn(false);
}

/**
 *
 * @param {Object} api
 */
function pushApiIfDoesNotExist(api) {
  var found = _.findWhere(descriptor.apis, {resourcePath: api.resourcePath});

  if (found) {
    return;
  }

  descriptor.apis.push(api);
}

/**
 *
 * @param {Function} fn
 * @returns {Function}
 */
function createParserCb(fn) {
  return function(err, docs) {

    if (err) {
      fn(err);
    }

    var resource = {apis: []};

    async.eachSeries(docs, function(doc, cb) {
      getSwagger(doc, function(api) {

        if (!api) {
          return cb();
        }

        // do not rewrite existing resource
        if (resources[api.resourcePath]) {
          resource = resources[api.resourcePath];
        }

        if (api.resourcePath) {
          pushApiIfDoesNotExist(api);
          resource.resourcePath = api.resourcePath;
        } else if (api.models) {
          resource.models = Object.assign({}, resource.models || {}, api.models);
        } else {
          resource.apis.push(api);
        }

        cb();
      });
    }, function() {
      if (resource.resourcePath){
        resources[resource.resourcePath] = resource;
      }
      fn();
    });
  };
}

/**
 * Read from jsDoc
 * @api    private
 * @param  {String}  file
 * @param  {Function} fn
 */
function readJsDoc(file, fn) {
  parseJsDocs(file, createParserCb(fn));
}

/**
 * Read from coffeeDoc
 * @api    private
 * @param  {String}  file
 * @param  {Function} fn
 */
function readCoffee(file, fn) {
  parseCoffeeDocs(file, createParserCb(fn));
}

/**
 * Read API from file
 * @api    private
 * @param  {String}   file
 * @param  {Function} fn
 */
function readApi(file, fn) {
  var ext = path.extname(file);
  if ('.js' === ext) {
    readJsDoc(file, fn);
  } else if ('.yml' === ext) {
    readYml(file, fn);
  } else if ('.coffee' === ext) {
    readCoffee(file, fn);
  } else {
    throw new Error('Unsupported extension \'' + ext + '\'');
  }
}

/**
 * Generate Swagger documents
 * @api    private
 * @param  {Object} opt
 */
function generate(opt) {
  if (!opt) {
    throw new Error('\'option\' is required.');
  }

  if (!opt.swaggerUI) {
    throw new Error('\'swaggerUI\' is required.');
  }

  if (!opt.basePath) {
    throw new Error('\'basePath\' is required.');
  }

  descriptor.basePath = opt.basePath;
  descriptor.apiVersion = (opt.apiVersion) ? opt.apiVersion : '1.0';
  descriptor.swaggerVersion = (opt.swaggerVersion) ? opt.swaggerVersion : '1.0';
  descriptor.swaggerURL = (opt.swaggerURL) ? opt.swaggerURL : '/swagger';
  descriptor.swaggerJSON = (opt.swaggerJSON) ? opt.swaggerJSON : '/api-docs.json';
  descriptor.apis = [];

  if (opt.info) {
    descriptor.info = opt.info;
  }

  opt.apiVersion = descriptor.apiVersion;
  opt.swaggerVersion = descriptor.swaggerVersion;
  opt.swaggerURL = descriptor.swaggerURL;
  opt.swaggerJSON = descriptor.swaggerJSON;

  if (!opt.fullSwaggerJSONPath) {
    opt.fullSwaggerJSONPath = url.parse(opt.basePath + opt.swaggerJSON).path;
  }

  if (opt.apis) {
    opt.apis.forEach(function(api) {
      readApi(api, function(err) {
        if (err) {
          throw err;
        }
      });
    });
  }
}

/**
 * Koa middleware
 * @api    public
 * @param  {Object} app
 * @param  {Object} opt
 * @return {Function}
 */
exports.init = function(opt) {
  // generate resources
  generate(opt);

  var app = koa();

  app.use(function *(next) {
    if (this.path === opt.swaggerURL) { // koa static barfs on root url w/o trailing slash
      this.redirect(this.path + '/');
    } else {
      yield next;
    }
  });

  app.use(mount(opt.swaggerURL, serve(opt.swaggerUI)));

  var swaggerJSON = function *(resourceName) {
    var result = _.clone(descriptor);

    if (resourceName) {
      if (resourceName==opt.singlePagePath){

        result.apis = []
        result.models ={}

        Object.keys(resources).forEach((name)=>{
          var resource = resources[name]
          for(var attribute in resource){
            if (Array.isArray(resource[attribute])){
              //arrays
              result[attribute] = result[attribute] || [];
              result[attribute] = result[attribute].concat(resource[attribute])
            }else if (typeof(resource[attribute])=='object'){
              // objects
              result[attribute] = result[attribute] || {};
              result[attribute] = Object.assign(result[attribute],resource[attribute])
            }else{
              // primatives (Strings / Numbers etc')
              result[attribute] = result[attribute] || resource[attribute];
            }

          }
        });

      }else{
        var resource = resources['/' + resourceName];

        if (!resource) {
          this.status = 404;
          return;
        }

        result.resourcePath = resource.resourcePath;
        result.apis = resource.apis;
        result.models = resource.models;
      }
    } else {

        result.apis = _.map(result.apis, function(api) {
          return {
            path: opt.swaggerJSON + api.resourcePath,
            description: api.description
          };
        });
    }

    this.body = result;
  };

  app.use(route.get(opt.fullSwaggerJSONPath + '/:resourceName*', swaggerJSON));

  return mount(app, '/');
};

exports.descriptor = descriptor;
exports.resources = resources;
<|endoftext|>


<commit_before>'use strict';

// stdlib
var http = require('http');
var zlib = require('zlib');
var url  = require('url');

// internal
var logger = require('./logger');
var getter = require('./common').getter;
var prop   = require('./common').prop;

var Server = function Server(environment, manifest) {
  prop(this, 'environment', environment);
  prop(this, 'manifest',    manifest);
};

// compresses buffer and fires `callback(err, str)`
function gzip_buffer(buff, callback) {
  zlib.createGzip().gzip(buff, callback);
}

var FINGERPRINT_RE = /-([0-9a-f]{32,40})\.[^.]+$/;
function get_fingerprint(pathname) {
  var m = FINGERPRINT_RE.exec(pathname);
  return m ? m[1] : null;
}

function end(res, code) {
  res.writeHead(code);
  res.end();
}

var BODY_ONLY_RE = /body=[1t]/;
function is_body_only(req) {
  var query = req.query || url.parse(req.url).query;
  BODY_ONLY_RE.test(query);
}

function etag(asset) {
  return '"' + asset.digest + '"';
}

function is_etag_match(req, asset) {
  return etag(asset) === (req.headers || {})['if-non-match'];
}

// Dummy Timer
function Timer () {
  this.__start__ = Date.now();

  this.stop = function () {
    return '(' + parseInt((this.__start__ - Date.now()) / 1000, 10) + 'ms)';
  };
}

Server.prototype.onRequest = function (req, res) {
  var self        = this,
      timer       = new Timer(),
      pathname    = url.parse(req.url).pathname,
      msg_prefix  = 'Served asset ' + req.url + ' - ',
      fingerprint = get_fingerprint(pathname);

  try {
    pathname = decodeURIComponent(pathname.replace(/^\//, ''));

    // NUL char? Something really strange happens
    if (-1 < pathname.indexOf("\u0000")) {
      logger.error(msg_prefix + 'URL contains NUL char');
      end(res, 400);
      return;
    }
  } catch (err) {
    logger.error(msg_prefix + 'Failed decode URL');
    end(res, 400);
    return;
  }

  // ignore requests with `..`
  if (0 <= pathname.indexOf('..')) {
    logger.error(msg_prefix + 'URL contains unsafe chars');
    end(res, 403);
    return;
  }

  // ignore non-GET requests
  if ('GET' !== req.method && 'HEAD' !== req.method) {
    logger.error(msg_prefix + "HTTP method '" + req.method + "' not allowed");
    end(res, 403);
    return;
  }

  // remove fingerprint (digest) from URL
  if (fingerprint) {
    pathname = pathname.replace('-' + fingerprint, '');
  }

  var asset = this.environment.findAsset(pathname, {bundle: !is_body_only(req)});

  // asset not found
  if (!asset) {
    logger.info(msg_prefix + "404 Not found " + timer.stop());
    end(res, 404);
    return;
  }

  asset.compile(function (err) {
    if (err) {
      logger.error(msg_prefix + "Error compiling asset " + pathname);
      logger.error(msg_prefix + (err.message || err.toString()));
      logger.info(msg_prefix + "500 Application Error " + timer.stop());
      end(res, 500);
      return;
    }

    // Not modified
    if (is_etag_match(req, asset)) {
      logger.info(msg_prefix + "304 Not Modified " + timer.stop());
      end(res, 304);
      return;
    }

    // OK
    logger.info(msg_prefix + "200 OK " + timer.stop());

    //
    // Set content type and length headers
    //

    res.setHeader("Content-Type",   asset.contentType);
    res.setHeader("Content-Length", asset.length);

    //
    // Set caching headers
    //

    if (fingerprint) {
      // If the request url contains a fingerprint, set a long
      // expires on the response
      res.setHeader("Cache-Control", "public, max-age=31536000");
    } else {
      // Otherwise set `must-revalidate` since the asset could be modified.
      res.setHeader("Cache-Control", "public, must-revalidate");
    }

    res.setHeader("Last-Modified",  asset.mtime.toUTCString());
    res.setHeader("ETag",           etag(asset));

    res.statusCode = 200;
    res.end(asset.buffer);
  });
};

module.exports = function (env, options) {
  var srv = new Server(env, options);
  return function (req, res) {
    return srv.onRequest(req, res);
  };
};
<commit_msg>Fix parsing ?body=1 requests<commit_after>'use strict';

// stdlib
var http = require('http');
var zlib = require('zlib');
var url  = require('url');

// internal
var logger = require('./logger');
var getter = require('./common').getter;
var prop   = require('./common').prop;

var Server = function Server(environment, manifest) {
  prop(this, 'environment', environment);
  prop(this, 'manifest',    manifest);
};

// compresses buffer and fires `callback(err, str)`
function gzip_buffer(buff, callback) {
  zlib.createGzip().gzip(buff, callback);
}

var FINGERPRINT_RE = /-([0-9a-f]{32,40})\.[^.]+$/;
function get_fingerprint(pathname) {
  var m = FINGERPRINT_RE.exec(pathname);
  return m ? m[1] : null;
}

function end(res, code) {
  res.writeHead(code);
  res.end();
}

var BODY_ONLY_RE = /body=[1t]/;
function is_body_only(req) {
  var query = req.query || url.parse(req.url).query;
  return BODY_ONLY_RE.test(query);
}

function etag(asset) {
  return '"' + asset.digest + '"';
}

function is_etag_match(req, asset) {
  return etag(asset) === (req.headers || {})['if-non-match'];
}

// Dummy Timer
function Timer () {
  this.__start__ = Date.now();

  this.stop = function () {
    return '(' + parseInt((this.__start__ - Date.now()) / 1000, 10) + 'ms)';
  };
}

Server.prototype.onRequest = function (req, res) {
  var self        = this,
      timer       = new Timer(),
      pathname    = url.parse(req.url).pathname,
      msg_prefix  = 'Served asset ' + req.url + ' - ',
      fingerprint = get_fingerprint(pathname);

  try {
    pathname = decodeURIComponent(pathname.replace(/^\//, ''));

    // NUL char? Something really strange happens
    if (-1 < pathname.indexOf("\u0000")) {
      logger.error(msg_prefix + 'URL contains NUL char');
      end(res, 400);
      return;
    }
  } catch (err) {
    logger.error(msg_prefix + 'Failed decode URL');
    end(res, 400);
    return;
  }

  // ignore requests with `..`
  if (0 <= pathname.indexOf('..')) {
    logger.error(msg_prefix + 'URL contains unsafe chars');
    end(res, 403);
    return;
  }

  // ignore non-GET requests
  if ('GET' !== req.method && 'HEAD' !== req.method) {
    logger.error(msg_prefix + "HTTP method '" + req.method + "' not allowed");
    end(res, 403);
    return;
  }

  // remove fingerprint (digest) from URL
  if (fingerprint) {
    pathname = pathname.replace('-' + fingerprint, '');
  }

  var asset = this.environment.findAsset(pathname, {bundle: !is_body_only(req)});

  // asset not found
  if (!asset) {
    logger.info(msg_prefix + "404 Not found " + timer.stop());
    end(res, 404);
    return;
  }

  asset.compile(function (err) {
    if (err) {
      logger.error(msg_prefix + "Error compiling asset " + pathname);
      logger.error(msg_prefix + (err.message || err.toString()));
      logger.info(msg_prefix + "500 Application Error " + timer.stop());
      end(res, 500);
      return;
    }

    // Not modified
    if (is_etag_match(req, asset)) {
      logger.info(msg_prefix + "304 Not Modified " + timer.stop());
      end(res, 304);
      return;
    }

    // OK
    logger.info(msg_prefix + "200 OK " + timer.stop());

    //
    // Set content type and length headers
    //

    res.setHeader("Content-Type",   asset.contentType);
    res.setHeader("Content-Length", asset.length);

    //
    // Set caching headers
    //

    if (fingerprint) {
      // If the request url contains a fingerprint, set a long
      // expires on the response
      res.setHeader("Cache-Control", "public, max-age=31536000");
    } else {
      // Otherwise set `must-revalidate` since the asset could be modified.
      res.setHeader("Cache-Control", "public, must-revalidate");
    }

    res.setHeader("Last-Modified",  asset.mtime.toUTCString());
    res.setHeader("ETag",           etag(asset));

    res.statusCode = 200;
    res.end(asset.buffer);
  });
};

module.exports = function (env, options) {
  var srv = new Server(env, options);
  return function (req, res) {
    return srv.onRequest(req, res);
  };
};
<|endoftext|>


<commit_before>// Copyright (c) 2017 The Regents of the University of Michigan.
// All Rights Reserved. Licensed according to the terms of the Revised
// BSD License. See LICENSE.txt for details.

module.exports = function(landscape) {
  let actions = new Map();
  let tickCount = 0;

  return {
    "tick": () => new Promise(function(resolve, reject) {
      try {
        tickCount += 1;

        if (actions.has(tickCount)) {
          let thing = actions.get(tickCount);
          landscape[thing.method].apply(landscape, thing.args);
        }

        resolve();

      } catch(error) {
        reject(error);
      }
    }),

    "at": function(when, method) {
      actions.set(when, {
        "when": when,
        "method": method,
        "args": [...arguments].slice(2)
      });
    }
  };
};
<commit_msg>:muscle: Store a mapping to lists instead of single actions<commit_after>// Copyright (c) 2017 The Regents of the University of Michigan.
// All Rights Reserved. Licensed according to the terms of the Revised
// BSD License. See LICENSE.txt for details.

module.exports = function(landscape) {
  let actions = new Map();
  let tickCount = 0;

  return {
    "tick": () => new Promise(function(resolve, reject) {
      try {
        tickCount += 1;

        if (actions.has(tickCount)) {
          let thing = actions.get(tickCount).pop();
          landscape[thing.method].apply(landscape, thing.args);
        }

        resolve();

      } catch(error) {
        reject(error);
      }
    }),

    "at": function(when, method) {
      if (!actions.has(when))
        actions.set(when, []);

      actions.get(when).push({
        "when": when,
        "method": method,
        "args": [...arguments].slice(2)
      });
    }
  };
};
<|endoftext|>


<commit_before>import mongoose from 'mongoose';

let Member = mongoose.model('Member', {
  username: String,
  firstName: String,
  lastName: String,
  chatId: Number
});

export default Member;<commit_msg>phone added to member schema<commit_after>import mongoose from 'mongoose';

let Member = mongoose.model('Member', {
  username: String,
  firstName: String,
  lastName: String,
  chatId: Number,
  phone: String
});

export default Member;<|endoftext|>


<commit_before><commit_msg>Compressed version<commit_after><|endoftext|>


<commit_before>// JavaScript Document

// Scripts written by __gulp_init_author_name__ @ __gulp_init_author_company__

import transition from "transition-to-from-auto";
import inViewport from "in-vp";

/**
 * Create an array of attribtes to target lists for
 */
const ATTRIBUTES = {
    classes:  ["menu-list", "menu-list__container--mega"],
    datasets: ["accordion", "hover", "touch"],
};

const SELECTOR = [];

/**
 * Create an array out of the CLASSES and DATAS in order to reduce duplicate code.
 */
ATTRIBUTES.classes.forEach((CLASS) => {
    ATTRIBUTES.datasets.forEach((DATA) => {
        SELECTOR.push(`.${CLASS}[data-${DATA}=true]`);
    });
});

/**
 * Find all MENU_LISTS which can be hovered or touched
 */
const MENU_LISTS = document.querySelectorAll(SELECTOR.join());

/**
 * Mark an item active
 *
 * @param {Object} LIST_ITEM - A DOM object to mark as active
 * @param {Object} MENU_LIST - A DOM object to mark as visible and reverse based on viewport
 * @param {Boolean} EVENT - An event to prevent from firing
 */
const MARK_ACTIVE = (LIST_ITEM, MENU_LIST, EVENT = false) => {
    /**
     * Prevent the EVENT from finishing unless the LIST_ITEM is already active
     */
    if (EVENT && !LIST_ITEM.classList.contains("is-active")) {
        EVENT.preventDefault();
    }

    /**
     * Mark the LIST_ITEM as active
     */
    LIST_ITEM.classList.add("is-active");

    /**
     * Transition open the MENU_LIST if it's an accordion
     */
    if (MENU_LIST.dataset.accordion === "true") {
        transition({ element: MENU_LIST, val: "auto" });
    }

    /**
     * Mark the MENU_LIST as aria-hidden="false"
     */
    MENU_LIST.setAttribute("aria-hidden", "false");

    /**
     * Reverse the MENU_LIST if it's not fully within the viewport
     */
    if (inViewport(MENU_LIST).fully === false) {
        MENU_LIST.classList.add("menu-list--reverse");
    }
};

/**
 * Mark an item and its children inactive
 *
 * @param {Object} LIST_ITEM - A DOM object to mark as inactive
 * @param {Object} MENU_LIST - A DOM object to mark as hidden and unreverse
 */
const MARK_INACTIVE = (LIST_ITEM, MENU_LIST) => {
    /**
     * Find any active CHILDREN
     */
    const CHILDREN = LIST_ITEM.querySelectorAll("is-active");

    /**
     * Recursively mark active CHILDREN as inactive
     */
    if (CHILDREN.length > 0) {
        CHILDREN.foreach((CHILD) => {
            MARK_INACTIVE(CHILD);
        });
    }

    /**
     * Mark the LIST_ITEM as inactive
     */
    LIST_ITEM.classList.remove("is-active");

    /**
     * Transition open the MENU_LIST if it's an accordion
     */
    if (MENU_LIST.dataset.accordion === "true") {
        transition({ element: MENU_LIST, val: 0 });
    }

    /**
     * Mark the MENU_LIST as aria-hidden="false"
     */
    MENU_LIST.setAttribute("aria-hidden", "true");

    /**
     * Unreverse the MENU_LIST
     */
    MENU_LIST.classList.remove("menu-list--reverse");
};

/**
 * Compare two sets of coordinates to determine if the user dragged
 *
 * @param {Object} START_COORDS - The coordinates where the user started their touch
 * @param {Object} END_COORDS - The coordinates where the user ended their touch
 * @param {Integer} THRESHOLD - The minimum distance in pixels to mark something as dragged
 */
const DID_USER_DRAG = (START_COORDS, END_COORDS, THRESHOLD = 10) => {
    return Math.abs(END_COORDS.clientX - START_COORDS.clientX) > THRESHOLD || Math.abs(END_COORDS.clientY - START_COORDS.clientY) > THRESHOLD;
};

/**
 * Store various events to listen for
 */
const EVENTS = {
    document:  ["click", "touchstart", "touchend"],
    list_item: {
        activate: {
            accordion: ["touchstart", "touchend"],
            hover:     ["mouseenter"],
            touch:     ["touchstart", "touchend"],
        },
        deactivate: ["mouseleave"],
    },
};

/**
 * Set up an object to track touches
 */
let start_coords = {clientX: 0, clientY: 0};
let end_coords   = {clientX: 0, clientY: 0};

/**
 * Listen for interactions on each menu
 */
MENU_LISTS.forEach((MENU_LIST) => {
    const LIST_ITEM   = MENU_LIST.closest(".menu-list__item");
    const MENU_TOGGLE = LIST_ITEM.querySelector(".menu-list__toggle");

    /**
     * Mark the LIST_ITEM as active when moused into or touched
     */
    for (const MODE in EVENTS.list_item.activate) {
        if (MENU_LIST.dataset[MODE] === "true") {

            for (const EVENT in EVENTS.list_item.activate[MODE]) {
                LIST_ITEM.addEventListener(EVENTS.list_item.activate[MODE][EVENT], (e) => {
                    /**
                     * Store the touchstart position
                     */
                    if (e.type === "touchstart") {
                        start_coords = e.touches[0];
                    }

                    /**
                     * Store the touchend position
                     */
                    if (e.type === "touchend") {
                        end_coords = e.changedTouches[0];
                    }

                    /**
                     * Mark the item as active if the event isn't touchstart and
                     * the user didn't drag their touch
                     */
                    if (e.type !== "touchstart" && !DID_USER_DRAG(start_coords, end_coords)) {
                        MARK_ACTIVE(LIST_ITEM, MENU_LIST, e);
                    }
                });
            }
        }
    }

    /**
     * Mark the LIST_ITEM as inactive when moused away
     */
    EVENTS.list_item.deactivate.forEach((EVENT) => {
        LIST_ITEM.addEventListener(EVENT, () => {
            MARK_INACTIVE(LIST_ITEM, MENU_LIST);
        }, { passive: true });
    });

    /**
     * Mark the LIST_ITEM as active or inactive when MENU_TOGGLE is clicked
     */
    MENU_TOGGLE.addEventListener("click", () => {
        if (!LIST_ITEM.classList.contains("is-active")) {
            MARK_ACTIVE(LIST_ITEM, MENU_LIST);
        } else {
            MARK_INACTIVE(LIST_ITEM, MENU_LIST);
        }
    });

    /**
     * Mark the LIST_ITEM as inactive when clicked away or touched away
     */
    EVENTS.document.forEach((EVENT) => {
        document.addEventListener(EVENT, (e) => {
            if (LIST_ITEM.classList.contains("is-active")) {
                /**
                 * Get the event path
                 */
                const PATH = e.path || (e.composedPath && e.composedPath());

                /**
                 * Determine if the LIST_ITEM is in the path of touched elements
                 */
                const LIST_ITEM_TOUCHED = PATH.some((ELEMENT) => {
                    return LIST_ITEM === ELEMENT;
                });

                /**
                 * Store the touchstart position
                 */
                if (e.type === "touchstart") {
                    start_coords = e.touches[0];
                }

                /**
                 * Store the touchend position
                 */
                if (e.type === "touchend") {
                    end_coords = e.changedTouches[0];
                }

                /**
                 * Mark the LIST_ITEM as inactive if it's not in the path of
                 * touched elements, and the user didn't drag their touch
                 */
                if (!LIST_ITEM_TOUCHED && !DID_USER_DRAG(start_coords, end_coords)) {
                    MARK_INACTIVE(LIST_ITEM, MENU_LIST);
                }
            }
        }, { passive: true });
    });
});
<commit_msg>Adjust object spacing<commit_after>// JavaScript Document

// Scripts written by __gulp_init_author_name__ @ __gulp_init_author_company__

import transition from "transition-to-from-auto";
import inViewport from "in-vp";

/**
 * Create an array of attribtes to target lists for
 */
const ATTRIBUTES = {
    classes:  ["menu-list", "menu-list__container--mega"],
    datasets: ["accordion", "hover", "touch"],
};

const SELECTOR = [];

/**
 * Create an array out of the CLASSES and DATAS in order to reduce duplicate code.
 */
ATTRIBUTES.classes.forEach((CLASS) => {
    ATTRIBUTES.datasets.forEach((DATA) => {
        SELECTOR.push(`.${CLASS}[data-${DATA}=true]`);
    });
});

/**
 * Find all MENU_LISTS which can be hovered or touched
 */
const MENU_LISTS = document.querySelectorAll(SELECTOR.join());

/**
 * Mark an item active
 *
 * @param {Object} LIST_ITEM - A DOM object to mark as active
 * @param {Object} MENU_LIST - A DOM object to mark as visible and reverse based on viewport
 * @param {Boolean} EVENT - An event to prevent from firing
 */
const MARK_ACTIVE = (LIST_ITEM, MENU_LIST, EVENT = false) => {
    /**
     * Prevent the EVENT from finishing unless the LIST_ITEM is already active
     */
    if (EVENT && !LIST_ITEM.classList.contains("is-active")) {
        EVENT.preventDefault();
    }

    /**
     * Mark the LIST_ITEM as active
     */
    LIST_ITEM.classList.add("is-active");

    /**
     * Transition open the MENU_LIST if it's an accordion
     */
    if (MENU_LIST.dataset.accordion === "true") {
        transition({ element: MENU_LIST, val: "auto" });
    }

    /**
     * Mark the MENU_LIST as aria-hidden="false"
     */
    MENU_LIST.setAttribute("aria-hidden", "false");

    /**
     * Reverse the MENU_LIST if it's not fully within the viewport
     */
    if (inViewport(MENU_LIST).fully === false) {
        MENU_LIST.classList.add("menu-list--reverse");
    }
};

/**
 * Mark an item and its children inactive
 *
 * @param {Object} LIST_ITEM - A DOM object to mark as inactive
 * @param {Object} MENU_LIST - A DOM object to mark as hidden and unreverse
 */
const MARK_INACTIVE = (LIST_ITEM, MENU_LIST) => {
    /**
     * Find any active CHILDREN
     */
    const CHILDREN = LIST_ITEM.querySelectorAll("is-active");

    /**
     * Recursively mark active CHILDREN as inactive
     */
    if (CHILDREN.length > 0) {
        CHILDREN.foreach((CHILD) => {
            MARK_INACTIVE(CHILD);
        });
    }

    /**
     * Mark the LIST_ITEM as inactive
     */
    LIST_ITEM.classList.remove("is-active");

    /**
     * Transition open the MENU_LIST if it's an accordion
     */
    if (MENU_LIST.dataset.accordion === "true") {
        transition({ element: MENU_LIST, val: 0 });
    }

    /**
     * Mark the MENU_LIST as aria-hidden="false"
     */
    MENU_LIST.setAttribute("aria-hidden", "true");

    /**
     * Unreverse the MENU_LIST
     */
    MENU_LIST.classList.remove("menu-list--reverse");
};

/**
 * Compare two sets of coordinates to determine if the user dragged
 *
 * @param {Object} START_COORDS - The coordinates where the user started their touch
 * @param {Object} END_COORDS - The coordinates where the user ended their touch
 * @param {Integer} THRESHOLD - The minimum distance in pixels to mark something as dragged
 */
const DID_USER_DRAG = (START_COORDS, END_COORDS, THRESHOLD = 10) => {
    return Math.abs(END_COORDS.clientX - START_COORDS.clientX) > THRESHOLD || Math.abs(END_COORDS.clientY - START_COORDS.clientY) > THRESHOLD;
};

/**
 * Store various events to listen for
 */
const EVENTS = {
    document:  ["click", "touchstart", "touchend"],
    list_item: {
        activate: {
            accordion: ["touchstart", "touchend"],
            hover:     ["mouseenter"],
            touch:     ["touchstart", "touchend"],
        },
        deactivate: ["mouseleave"],
    },
};

/**
 * Set up an object to track touches
 */
let start_coords = { clientX: 0, clientY: 0 };
let end_coords   = { clientX: 0, clientY: 0 };

/**
 * Listen for interactions on each menu
 */
MENU_LISTS.forEach((MENU_LIST) => {
    const LIST_ITEM   = MENU_LIST.closest(".menu-list__item");
    const MENU_TOGGLE = LIST_ITEM.querySelector(".menu-list__toggle");

    /**
     * Mark the LIST_ITEM as active when moused into or touched
     */
    for (const MODE in EVENTS.list_item.activate) {
        if (MENU_LIST.dataset[MODE] === "true") {

            for (const EVENT in EVENTS.list_item.activate[MODE]) {
                LIST_ITEM.addEventListener(EVENTS.list_item.activate[MODE][EVENT], (e) => {
                    /**
                     * Store the touchstart position
                     */
                    if (e.type === "touchstart") {
                        start_coords = e.touches[0];
                    }

                    /**
                     * Store the touchend position
                     */
                    if (e.type === "touchend") {
                        end_coords = e.changedTouches[0];
                    }

                    /**
                     * Mark the item as active if the event isn't touchstart and
                     * the user didn't drag their touch
                     */
                    if (e.type !== "touchstart" && !DID_USER_DRAG(start_coords, end_coords)) {
                        MARK_ACTIVE(LIST_ITEM, MENU_LIST, e);
                    }
                });
            }
        }
    }

    /**
     * Mark the LIST_ITEM as inactive when moused away
     */
    EVENTS.list_item.deactivate.forEach((EVENT) => {
        LIST_ITEM.addEventListener(EVENT, () => {
            MARK_INACTIVE(LIST_ITEM, MENU_LIST);
        }, { passive: true });
    });

    /**
     * Mark the LIST_ITEM as active or inactive when MENU_TOGGLE is clicked
     */
    MENU_TOGGLE.addEventListener("click", () => {
        if (!LIST_ITEM.classList.contains("is-active")) {
            MARK_ACTIVE(LIST_ITEM, MENU_LIST);
        } else {
            MARK_INACTIVE(LIST_ITEM, MENU_LIST);
        }
    });

    /**
     * Mark the LIST_ITEM as inactive when clicked away or touched away
     */
    EVENTS.document.forEach((EVENT) => {
        document.addEventListener(EVENT, (e) => {
            if (LIST_ITEM.classList.contains("is-active")) {
                /**
                 * Get the event path
                 */
                const PATH = e.path || (e.composedPath && e.composedPath());

                /**
                 * Determine if the LIST_ITEM is in the path of touched elements
                 */
                const LIST_ITEM_TOUCHED = PATH.some((ELEMENT) => {
                    return LIST_ITEM === ELEMENT;
                });

                /**
                 * Store the touchstart position
                 */
                if (e.type === "touchstart") {
                    start_coords = e.touches[0];
                }

                /**
                 * Store the touchend position
                 */
                if (e.type === "touchend") {
                    end_coords = e.changedTouches[0];
                }

                /**
                 * Mark the LIST_ITEM as inactive if it's not in the path of
                 * touched elements, and the user didn't drag their touch
                 */
                if (!LIST_ITEM_TOUCHED && !DID_USER_DRAG(start_coords, end_coords)) {
                    MARK_INACTIVE(LIST_ITEM, MENU_LIST);
                }
            }
        }, { passive: true });
    });
});
<|endoftext|>