<commit_before>/**
 * Network class
 */
var Network = (function () {

    // Instance stores a reference to the Singleton
    var instance;

    var TCP_TYPE = 1;
    var UDP_TYPE = 2;

    function init() {

        var multicastSocket;
        var tcpServerSockets = [];
        var replicationRequestTCPSockets = [];

        // initialize sockets array
//        var sockets = [];
//        sockets[TCP_TYPE] = [];
//        sockets[UDP_TYPE] = [];

        var pendingMessages = [];
        var pendingMulticastMessages = [];

//        var UDP_CREATED = false;

        var UDP_MULTICAST_CREATED = false;

        var networkInterfaces = [];

        /**
         * DEAD CODE
         * @param resolve
         * @param port
         */
        function createMulticastTCPSocket(resolve, port) {
            log("Hitting DEAD CODE!");
        }

        /**
         * Helper function to get the network interface object
         * for a given an IP assigned to the current host.
         * @param ip
         * @returns {*}
         */
        function getNetworkInterfaceForIP(ip) {
            var result;
            networkInterfaces.forEach(function (ni) {
                if (ni.ip == ip) {
                    result = ni;
                }
            });
            return result;
        }

        /**
         * Checks if there is a socket of for the given port and protocol.
         * @param protocol
         * @param port
         * @returns {boolean}
         */
        function hasSocket(protocol, port) {
            var result = false;
            sockets[protocol].forEach(function (socket) {
                if (socket.protocol == protocol &&
                        socket.port == port) {
                    result = true;
                }
            });
            return result;
        }

        /**
         *
         * @param protocol
         * @param port
         * @returns {boolean}
         */
        function hasMulticastSocket(protocol, port) {

            if (protocol !== UDP_TYPE &&
                    port !== MulticastReplicationProtocol.Port) {
                log("Multicast socket not created");
                return false;
            } else if (typeof multicastSocket !== 'undefined') {
                log("Multicast socket was created");
                log("Typeof multicasSocket ", multicastSocket);
                return true;
            }
        }

        /**
         * Sets the flag that indicates that a UDP socket was created.
         * @param value
         */
        function setMulticastUDPCreatedFlag(value) {
            debug("Setting up flag for UDP socket creation");
            if (!value) {
                UDP_MULTICAST_CREATED = value;
                return;
            }

            pendingMulticastMessages.forEach(function (msg) {
                log("Multicast message", msg);
                log(msg.toString());
            });

            UDP_MULTICAST_CREATED = value;

            pendingMulticastMessages.forEach(function (msg) {
                sendMulticastMessage(msg.ip, msg.port, msg, msg.callback);
            });

            pendingMulticastMessages = [];
        }

        /**
         *
         * @param error
         * @param step
         * @param data
         */
        function handleSocketCreationError(error, step, data) {

            var msg = "Error [" + error + "]: ";

            switch (step) {
                case 1:
                    msg = msg + "Socket could not be created.";
                    break;
                case 2:
                    msg = msg + "Socket Multicast TTL could not be set.";
                    break;
                case 3:
                    msg = msg + "Loopback mode could not be set.";
                    break;
                case 4:
                    msg = msg + "Socket bind could not be performed.";
                    break;
                case 5:
                    msg = msg + "Multicast group could not be joined.";
                    break;
                case 6:
                    msg = msg + "No delay could not be set.";
                    break;
                case 7:
                    msg = msg + "Could not set paused.";
                    break;
                case 8:
                    msg = msg + "Could not connect socket.";
                    break;
            }

            log(msg);

            if (data) {
                log("Extra data: " + JSON.stringify(data));
            }

        }

        function sendMessageThroughNewSocket(peerIp, peerPort, messageObj) {

            chrome.sockets.tcp.create({}, function (socketInfo) {

                var socketId = socketInfo.socketId;

                replicationRequestTCPSockets.push(socketId);

                if (socketId < 0) {
                    handleSocketCreationError(socketId, 1, socketInfo);
                    return;
                }

//                chrome.sockets.tcp.setNoDelay(socketId, false, function (result) {

//                    if (result < 0) {
//                        handleSocketCreationError(result, 6, socketInfo);
//                        return;
//                    }

                    chrome.sockets.tcp.setPaused(socketId, false, function (result) {

                        if (result < 0) {
                            handleSocketCreationError(result, 7, socketInfo);
                            return;
                        }

                        chrome.sockets.tcp.connect(socketId, peerIp, peerPort, function () {

                            if (result < 0) {
                                handleSocketCreationError(result, 8, socketInfo);
                                return;
                            }

                            var arrayBuffer = messageObj.getPreparedContent();

                            chrome.sockets.tcp.send(socketId, arrayBuffer, function (sendInfo) {
                                debug("Message sent through TCP socket: " + messageObj.getPayload().toJSON(), messageObj);
                            });

                        });

                    });
//
//
//                });

            });
        }

        /**
         * @param port
         * @param onReceive
         */
        function createTCPServerSocket(resolve, ip, port) {

            log("Creating TCP Socket on [" + ip + ":" + port + "] ");

            chrome.sockets.tcpServer.create({}, function (socketInfo) {

                var socketId = socketInfo.socketId;

                if (socketId < 0) {
                    handleSocketCreationError(socketId, 1, socketInfo);
                    return;
                }

                chrome.sockets.tcpServer.listen(socketId, ip, port, function (result) {

                    if (result < 0) {
                        handleSocketCreationError(result, 6, socketInfo);
                        return;
                    }

                    debug("TCP Server socket listening on " + ip + ":" + port + "...");

                    resolve();

                });
            });

        }

        function createMuticastUDPSocket(resolve, port, onReceive) {

            // Create the Socket
            chrome.sockets.udp.create({}, function (socketInfo) {

                if (socketInfo.socketId < 0) {
                    handleSocketCreationError(socketInfo.socketId, 1, socketInfo);
                    return;
                }
                var socketId = socketInfo.socketId;
                var localIp = "0.0.0.0";

                // Set multicast TTL
                chrome.sockets.udp.setMulticastTimeToLive(socketId, 12, function (result) {

                    if (result < 0) {
                        handleSocketCreationError(result, 2);
                        return;
                    }

                    // Set onReceive callback
                    chrome.sockets.udp.onReceive.addListener(onReceive);

                    // Disable loopback on multicast
                    chrome.sockets.udp.setMulticastLoopbackMode(socketId, false, function (result) {

                        if (result < 0) {
                            handleSocketCreationError(result, 3);
                            return;
                        }

                        // Bind the socket to the desired port
                        chrome.sockets.udp.bind(socketId, localIp, port, function (result) {

                            if (result < 0) {
                                handleSocketCreationError(result, 4);
                                return;
                            }

//                            var socket = new Socket(socketId, port, UDP_TYPE);
//                            sockets[UDP_TYPE].push(socket);
                            multicastSocket = new Socket(socketId, port, UDP_TYPE);

                            // Join the multicast group where replication occurs
                            chrome.sockets.udp.joinGroup(socketId, MulticastReplicationProtocol.MulticastIP, function (result) {

                                if (result < 0) {
                                    handleSocketCreationError(result, 5);
                                    return;
                                }

                                resolve(localIp);

                                // Debugging: list the multicast groups joined
                                chrome.sockets.udp.getJoinedGroups(socketId, function (val) {
                                    debug("[" + socketId + "] joined groups for ip " + MulticastReplicationProtocol.MulticastIP + " [sockeId:" + socketId + "]");
                                    debug(val);
                                });

                            });

                        });

                    });
                });
            });
        }

        /**
         * Send simple UDP message to the given ip:port
         * @param ip
         * @param port
         * @param arrayBuffer
         */
        function sendUDPMessage(ip, port, m) {

            var stringMsg = JSON.stringify(m.content);
            var arrayBuffer = MessageEncoder.str2ab(stringMsg);

            /**
             * TODO: add code to select the right socket.
             * For now, everything through the multicast socket.
             * @type {*}
             */
            var socket = multicastSocket;

            chrome.sockets.udp.send(socket.id, arrayBuffer, ip, port, function (sendInfo) {
                debug("Message [" + msg.msg + "] sent to [" + ip + ":" + port + "] through socket with id [" + socket.id + "]");
                debug("Send Info is:" + sendInfo.resultCode);
            });
        }

        /**
         *
         * @param multicastIp
         * @param port
         * @param messageObj Message
         * @param callback
         */
        function sendMulticastMessage(multicastIp, port, messageObj, callback) {

            var arrayBuffer = messageObj.getPreparedContent();

            var cb;
            if (messageObj.callback) {
                cb = messageObj.callback;
            } else {
                cb = callback;
            }

            chrome.sockets.udp.send(multicastSocket.id, arrayBuffer, multicastIp, port, cb);
        }

        return {

            TCP_TYPE: TCP_TYPE,
            UDP_TYPE: UDP_TYPE,

            getNetworkInterfaces: function () {
                return networkInterfaces;
            },

            /**
             * Send message to
             * @param ip
             * @param port
             * @param type
             * @param msg
             * @returns {boolean}
             */
//            sendUDPMessage: function (ip, port, msg) {
//
//                var m = new Message(type, msg);
//
//                if (UDP_CREATED == false) {
//                    debug("Trying to send message, but no UDP socket created. Queueing the message.");
//                    m.ip = ip;
//                    m.port = port;
//                    pendingMessages.push(m);
//                    return false;
//                }
//
//                debug("Sending inline, not delayed.");
//
//                sendUDPMessage(ip, port, m);
//
//                return true;
//            },

            /**
             * Send multicast message over UDP
             *
             * @param multicastIp
             * @param port
             * @param messageObj
             * @param callback
             */
            sendMulticastMessage: function (multicastIp, port, messageObj, callback) {

                if (!hasMulticastSocket(UDP_TYPE, port)) {
                    debug("Trying to send multicast message, but no multicast UDP socket created. Queueing the message.");
                    messageObj.ip = multicastIp;
                    messageObj.port = port;
                    messageObj.callback = callback;
                    debug("Pushed this message to pending messages:", JSON.stringify(messageObj));
                    pendingMulticastMessages.push(messageObj);
                    return false;
                }

                debug("Sending inline, not delayed.");

                sendMulticastMessage(multicastIp, port, messageObj, callback);

                return true;
            },

            /**
             * Create a multicast socket over the given protocol, port and
             * call the callback onReceive when new data is available.
             * @param type
             * @param port
             * @param onReceive
             */
            createMulticastSocket: function (port, onReceive) {

                debug("Creating UDP Multicast socket on port[" + port + "]");

                var checkUDPSocketCreation = function () {
                    debug("Created multicast UDP socket on [" + port + "].");
                    setMulticastUDPCreatedFlag(true);
                }

                createMuticastUDPSocket(checkUDPSocketCreation, port, onReceive);
            },

//            createSocket: function (type, port, onReceive) {
//                debug("Creating socket with type[" + type + "] and port[" + port + "]");
//
//                createTCPSocket(port, onReceive);
//            },

            createTCPServerSockets: function (onReceive) {

                var onAccept = function (info) {
                    var socketId = info.socketId;
                    var clientSocketId = info.clientSocketId;

                    debug("Connection on socket [" + socketId + "] accepted. Should reply through socket [" + clientSocketId + "]", info);

                    // should unpause the socket
                    chrome.sockets.tcp.setPaused(clientSocketId, false, function () {
                        debug("Socket unpaused.");
                    });
                };

                chrome.sockets.tcpServer.onAccept.addListener(onAccept);

                var onReceive_tpZ9u193HAY9 = function (data){

                    var socketId = data.socketId;
                    var msg = Message.CreateFromRawData(Message.Types.IN, data.data);

                    onReceive(msg, socketId);
                };

                chrome.sockets.tcp.onReceive.addListener(onReceive_tpZ9u193HAY9);

                var tcpServerSocketCreated = function () {
                    if (networkInterfaces.length == tcpServerSockets.length) {
                        debug("All TCP server sockets created.");
                    }
                };

                networkInterfaces.forEach(function (ni) {
                    createTCPServerSocket(tcpServerSocketCreated, ni.ip, DirectReplicationProtocol.Port);
                });

            },

            sendMessageThroughNewSocket: function (peerIp, peerPort, msg) {
                sendMessageThroughNewSocket(peerIp, peerPort, msg);
            },

            /**
             * Load network interfaces and call resolve when all loaded.
             * @param resolve
             */
            loadNetworkInterfaces: function (resolve) {

                chrome.system.network.getNetworkInterfaces(function (ni) {
                    debug("We got the network interfaces.");

                    var identityString = "";

                    ni.forEach(function (el) {
                        var regEx = new RegExp('^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$');
                        if (regEx.test(el.address) == true) {
                            networkInterfaces[networkInterfaces.length] = new NetworkInterface(el.address, el.prefixLength, el.name);
                            identityString += "|" + el.address;
                        }
                    });

                    log("IdentityString: " + identityString);

                    var identity = ReplicaIdentity.new(identityString.hashCode(), new Date().getTime());
                    var c = Context.getInstance();

                    c.setReplicaIdentity(identity);

                    log("After hashing: " + identity.toString());

                    resolve();
                });

            }

        };

    }

    return {

        // Get the Singleton instance if one exists
        // or create one if it doesn't
        getInstance: function () {

            if (!instance) {
                instance = init();
            }

            return instance;
        }

    };

})();

<commit_msg>Adding support to send message through existing socket and release socket once the communication has ended and the socket is no longer needed.<commit_after>/**
 * Network class
 */
var Network = (function () {

    // Instance stores a reference to the Singleton
    var instance;

    var TCP_TYPE = 1;
    var UDP_TYPE = 2;

    function init() {

        var multicastSocket;
        var tcpServerSockets = [];
        var replicationRequestTCPSockets = [];

        // initialize sockets array
//        var sockets = [];
//        sockets[TCP_TYPE] = [];
//        sockets[UDP_TYPE] = [];

        var pendingMessages = [];
        var pendingMulticastMessages = [];

//        var UDP_CREATED = false;

        var UDP_MULTICAST_CREATED = false;

        var networkInterfaces = [];

        /**
         * DEAD CODE
         * @param resolve
         * @param port
         */
        function createMulticastTCPSocket(resolve, port) {
            log("Hitting DEAD CODE!");
        }

        /**
         * Helper function to get the network interface object
         * for a given an IP assigned to the current host.
         * @param ip
         * @returns {*}
         */
        function getNetworkInterfaceForIP(ip) {
            var result;
            networkInterfaces.forEach(function (ni) {
                if (ni.ip == ip) {
                    result = ni;
                }
            });
            return result;
        }

        /**
         * Checks if there is a socket of for the given port and protocol.
         * @param protocol
         * @param port
         * @returns {boolean}
         */
        function hasSocket(protocol, port) {
            var result = false;
            sockets[protocol].forEach(function (socket) {
                if (socket.protocol == protocol &&
                        socket.port == port) {
                    result = true;
                }
            });
            return result;
        }

        /**
         *
         * @param protocol
         * @param port
         * @returns {boolean}
         */
        function hasMulticastSocket(protocol, port) {

            if (protocol !== UDP_TYPE &&
                    port !== MulticastReplicationProtocol.Port) {
                log("Multicast socket not created");
                return false;
            } else if (typeof multicastSocket !== 'undefined') {
                log("Multicast socket was created");
                log("Typeof multicasSocket ", multicastSocket);
                return true;
            }
        }

        /**
         * Sets the flag that indicates that a UDP socket was created.
         * @param value
         */
        function setMulticastUDPCreatedFlag(value) {
            debug("Setting up flag for UDP socket creation");
            if (!value) {
                UDP_MULTICAST_CREATED = value;
                return;
            }

            pendingMulticastMessages.forEach(function (msg) {
                log("Multicast message", msg);
                log(msg.toString());
            });

            UDP_MULTICAST_CREATED = value;

            pendingMulticastMessages.forEach(function (msg) {
                sendMulticastMessage(msg.ip, msg.port, msg, msg.callback);
            });

            pendingMulticastMessages = [];
        }

        /**
         *
         * @param error
         * @param step
         * @param data
         */
        function handleSocketCreationError(error, step, data) {

            var msg = "Error [" + error + "]: ";

            switch (step) {
                case 1:
                    msg = msg + "Socket could not be created.";
                    break;
                case 2:
                    msg = msg + "Socket Multicast TTL could not be set.";
                    break;
                case 3:
                    msg = msg + "Loopback mode could not be set.";
                    break;
                case 4:
                    msg = msg + "Socket bind could not be performed.";
                    break;
                case 5:
                    msg = msg + "Multicast group could not be joined.";
                    break;
                case 6:
                    msg = msg + "No delay could not be set.";
                    break;
                case 7:
                    msg = msg + "Could not set paused.";
                    break;
                case 8:
                    msg = msg + "Could not connect socket.";
                    break;
            }

            log(msg);

            if (data) {
                log("Extra data: " + JSON.stringify(data));
            }

        }

        /**
         *
         * @param socketId
         * @param messageObj
         */
        function sendMessageThroughExistingSocket(socketId, messageObj){

            var arrayBuffer = messageObj.getPreparedContent();

            chrome.sockets.tcp.send(socketId, arrayBuffer, function(sendInfo){
                var msgPayload = messageObj.getPayload();
                log("Sent message through socketId["+socketId+"]: "+msgPayload.toJSON());

                chrome.sockets.tcp.close(socketId, function (){
                    log("Socket with ID ["+socketId+"] closed successfully");
                });
            });

        }

        function sendMessageThroughNewSocket(peerIp, peerPort, messageObj) {

            chrome.sockets.tcp.create({}, function (socketInfo) {

                var socketId = socketInfo.socketId;

                replicationRequestTCPSockets.push(socketId);

                if (socketId < 0) {
                    handleSocketCreationError(socketId, 1, socketInfo);
                    return;
                }

//                chrome.sockets.tcp.setNoDelay(socketId, false, function (result) {

//                    if (result < 0) {
//                        handleSocketCreationError(result, 6, socketInfo);
//                        return;
//                    }

                    chrome.sockets.tcp.setPaused(socketId, false, function (result) {

                        if (result < 0) {
                            handleSocketCreationError(result, 7, socketInfo);
                            return;
                        }

                        chrome.sockets.tcp.connect(socketId, peerIp, peerPort, function () {

                            if (result < 0) {
                                handleSocketCreationError(result, 8, socketInfo);
                                return;
                            }

                            var arrayBuffer = messageObj.getPreparedContent();

                            chrome.sockets.tcp.send(socketId, arrayBuffer, function (sendInfo) {
                                debug("Message sent through TCP socket["+socketId+"] : " + messageObj.getPayload().toJSON());
                            });

                        });

                    });
//
//
//                });

            });
        }

        /**
         * @param port
         * @param onReceive
         */
        function createTCPServerSocket(resolve, ip, port) {

            log("Creating TCP Socket on [" + ip + ":" + port + "] ");

            chrome.sockets.tcpServer.create({}, function (socketInfo) {

                var socketId = socketInfo.socketId;

                if (socketId < 0) {
                    handleSocketCreationError(socketId, 1, socketInfo);
                    return;
                }

                chrome.sockets.tcpServer.listen(socketId, ip, port, function (result) {

                    if (result < 0) {
                        handleSocketCreationError(result, 6, socketInfo);
                        return;
                    }

                    debug("TCP Server socket listening on " + ip + ":" + port + "...");

                    resolve();

                });
            });

        }

        function createMuticastUDPSocket(resolve, port, onReceive) {

            // Create the Socket
            chrome.sockets.udp.create({}, function (socketInfo) {

                if (socketInfo.socketId < 0) {
                    handleSocketCreationError(socketInfo.socketId, 1, socketInfo);
                    return;
                }
                var socketId = socketInfo.socketId;
                var localIp = "0.0.0.0";

                // Set multicast TTL
                chrome.sockets.udp.setMulticastTimeToLive(socketId, 12, function (result) {

                    if (result < 0) {
                        handleSocketCreationError(result, 2);
                        return;
                    }

                    // Set onReceive callback
                    chrome.sockets.udp.onReceive.addListener(onReceive);

                    // Disable loopback on multicast
                    chrome.sockets.udp.setMulticastLoopbackMode(socketId, false, function (result) {

                        if (result < 0) {
                            handleSocketCreationError(result, 3);
                            return;
                        }

                        // Bind the socket to the desired port
                        chrome.sockets.udp.bind(socketId, localIp, port, function (result) {

                            if (result < 0) {
                                handleSocketCreationError(result, 4);
                                return;
                            }

//                            var socket = new Socket(socketId, port, UDP_TYPE);
//                            sockets[UDP_TYPE].push(socket);
                            multicastSocket = new Socket(socketId, port, UDP_TYPE);

                            // Join the multicast group where replication occurs
                            chrome.sockets.udp.joinGroup(socketId, MulticastReplicationProtocol.MulticastIP, function (result) {

                                if (result < 0) {
                                    handleSocketCreationError(result, 5);
                                    return;
                                }

                                resolve(localIp);

                                // Debugging: list the multicast groups joined
                                chrome.sockets.udp.getJoinedGroups(socketId, function (val) {
                                    debug("[" + socketId + "] joined groups for ip " + MulticastReplicationProtocol.MulticastIP + " [sockeId:" + socketId + "]");
                                    debug(val);
                                });

                            });

                        });

                    });
                });
            });
        }

        /**
         * Send simple UDP message to the given ip:port
         * @param ip
         * @param port
         * @param arrayBuffer
         */
        function sendUDPMessage(ip, port, m) {

            var stringMsg = JSON.stringify(m.content);
            var arrayBuffer = MessageEncoder.str2ab(stringMsg);

            /**
             * TODO: add code to select the right socket.
             * For now, everything through the multicast socket.
             * @type {*}
             */
            var socket = multicastSocket;

            chrome.sockets.udp.send(socket.id, arrayBuffer, ip, port, function (sendInfo) {
                debug("Message [" + msg.msg + "] sent to [" + ip + ":" + port + "] through socket with id [" + socket.id + "]");
                debug("Send Info is:" + sendInfo.resultCode);
            });
        }

        /**
         *
         * @param multicastIp
         * @param port
         * @param messageObj Message
         * @param callback
         */
        function sendMulticastMessage(multicastIp, port, messageObj, callback) {

            var arrayBuffer = messageObj.getPreparedContent();

            var cb;
            if (messageObj.callback) {
                cb = messageObj.callback;
            } else {
                cb = callback;
            }

            chrome.sockets.udp.send(multicastSocket.id, arrayBuffer, multicastIp, port, cb);
        }

        function releaseSocket(socketId, type){

            switch(type){
                case TCP_TYPE:
                        chrome.sockets.tcp.disconnect(socketId, function (){
                           chrome.sockets.tcp.close(socketId, function(){
                               log("TCP Socket with ID "+socketId+" closed correctly.");
                           })
                        });
                    break;
                case UDP_TYPE:
                        chrome.sockets.udp.close(socketId, function (){
                                log("UDP Socket with ID "+socketId+" closed correctly.");
                        });
                    break;
                default:
                    log("Don't know how to close socket ["+socketId+"] of type ["+type+"]");
            }
        }

        return {

            TCP_TYPE: TCP_TYPE,
            UDP_TYPE: UDP_TYPE,

            getNetworkInterfaces: function () {
                return networkInterfaces;
            },

            /**
             * Send message to
             * @param ip
             * @param port
             * @param type
             * @param msg
             * @returns {boolean}
             */
//            sendUDPMessage: function (ip, port, msg) {
//
//                var m = new Message(type, msg);
//
//                if (UDP_CREATED == false) {
//                    debug("Trying to send message, but no UDP socket created. Queueing the message.");
//                    m.ip = ip;
//                    m.port = port;
//                    pendingMessages.push(m);
//                    return false;
//                }
//
//                debug("Sending inline, not delayed.");
//
//                sendUDPMessage(ip, port, m);
//
//                return true;
//            },

            /**
             * Send multicast message over UDP
             *
             * @param multicastIp
             * @param port
             * @param messageObj
             * @param callback
             */
            sendMulticastMessage: function (multicastIp, port, messageObj, callback) {

                if (!hasMulticastSocket(UDP_TYPE, port)) {
                    debug("Trying to send multicast message, but no multicast UDP socket created. Queueing the message.");
                    messageObj.ip = multicastIp;
                    messageObj.port = port;
                    messageObj.callback = callback;
                    debug("Pushed this message to pending messages:", JSON.stringify(messageObj));
                    pendingMulticastMessages.push(messageObj);
                    return false;
                }

                debug("Sending inline, not delayed.");

                sendMulticastMessage(multicastIp, port, messageObj, callback);

                return true;
            },

            /**
             * Create a multicast socket over the given protocol, port and
             * call the callback onReceive when new data is available.
             * @param type
             * @param port
             * @param onReceive
             */
            createMulticastSocket: function (port, onReceive) {

                debug("Creating UDP Multicast socket on port[" + port + "]");

                var checkUDPSocketCreation = function () {
                    debug("Created multicast UDP socket on [" + port + "].");
                    setMulticastUDPCreatedFlag(true);
                }

                createMuticastUDPSocket(checkUDPSocketCreation, port, onReceive);
            },

//            createSocket: function (type, port, onReceive) {
//                debug("Creating socket with type[" + type + "] and port[" + port + "]");
//
//                createTCPSocket(port, onReceive);
//            },

            createTCPServerSockets: function (onReceive) {

                var onAccept = function (info) {
                    var socketId = info.socketId;
                    var clientSocketId = info.clientSocketId;

                    debug("Connection on socket [" + socketId + "] accepted. Should reply through socket [" + clientSocketId + "]", info);

                    // should unpause the socket
                    chrome.sockets.tcp.setPaused(clientSocketId, false, function () {
                        debug("Socket unpaused.");
                    });
                };

                chrome.sockets.tcpServer.onAccept.addListener(onAccept);

                var onReceive_tpZ9u193HAY9 = function (data){
                    onReceive(data.data, data.socketId);
                };

                chrome.sockets.tcp.onReceive.addListener(onReceive_tpZ9u193HAY9);

                var tcpServerSocketCreated = function () {
                    if (networkInterfaces.length == tcpServerSockets.length) {
                        debug("All TCP server sockets created.");
                    }
                };

                networkInterfaces.forEach(function (ni) {
                    createTCPServerSocket(tcpServerSocketCreated, ni.ip, DirectReplicationProtocol.Port);
                });

            },

            sendMessageThroughNewSocket: function (peerIp, peerPort, msg) {
                sendMessageThroughNewSocket(peerIp, peerPort, msg);
            },

            sendMessageThroughExistingSocket: function (socketId, msg){
                sendMessageThroughExistingSocket(socketId, msg);
            },

            /**
             * Load network interfaces and call resolve when all loaded.
             * @param resolve
             */
            loadNetworkInterfaces: function (resolve) {

                chrome.system.network.getNetworkInterfaces(function (ni) {
                    debug("We got the network interfaces.");

                    var identityString = "";

                    ni.forEach(function (el) {
                        var regEx = new RegExp('^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$');
                        if (regEx.test(el.address) == true) {
                            networkInterfaces[networkInterfaces.length] = new NetworkInterface(el.address, el.prefixLength, el.name);
                            identityString += "|" + el.address;
                        }
                    });

                    log("IdentityString: " + identityString);

                    var identity = ReplicaIdentity.new(identityString.hashCode(), new Date().getTime());
                    var c = Context.getInstance();

                    c.setReplicaIdentity(identity);

                    log("After hashing: " + identity.toString());

                    resolve();
                });
            },

            releaseSocket: function (socketId, type){
                releaseSocket(socketId, type);
            }

        };

    }

    return {

        // Get the Singleton instance if one exists
        // or create one if it doesn't
        getInstance: function () {

            if (!instance) {
                instance = init();
            }

            return instance;
        }

    };

})();

<|endoftext|>


<commit_before>Prism.languages.clike = {
	'comment': {
		pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|[^:]\/\/.*?(\r?\n|$))/g,
		lookbehind: true
	},
	'string': /("|')(\\?.)*?\1/g,
	'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|catch|finally|null|break|continue)\b/g,
	'boolean': /\b(true|false)\b/g,
	'number': /\b-?(0x)?\d*\.?[\da-f]+\b/g,
	'operator': /[-+]{1,2}|!|=?<|=?>|={1,2}|(&){1,2}|\|?\||\?|\*|\//g,
	'ignore': /&(lt|gt|amp);/gi,
	'punctuation': /[{}[\];(),.:]/g
};<commit_msg>Added missing operators for c-like languages<commit_after>Prism.languages.clike = {
	'comment': {
		pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|[^:]\/\/.*?(\r?\n|$))/g,
		lookbehind: true
	},
	'string': /("|')(\\?.)*?\1/g,
	'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|catch|finally|null|break|continue)\b/g,
	'boolean': /\b(true|false)\b/g,
	'number': /\b-?(0x)?\d*\.?[\da-f]+\b/g,
	'operator': /[-+]{1,2}|!|=?<|=?>|={1,2}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,
	'ignore': /&(lt|gt|amp);/gi,
	'punctuation': /[{}[\];(),.:]/g
};<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2018  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('14.8.0');
		this.setClientTag('node:18-11-19');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2018  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('14.8.0');
		this.setClientTag('node:18-11-20');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>


<commit_before>import test from 'ava';
import path from 'path';
import chalk from 'chalk';
import json from 'json-extra';
import getConfig from '../lib/getConfig';
import { choices, questions } from '../lib/promptConfig';

const cwd = process.cwd();

test('get configuration file equals .sgcrc_default', (t) => {
  t.deepEqual(getConfig(), json.readToObjSync(path.join(cwd, '.sgcrc_default')));
});

test('choices are the same as choices generated from .sgcrc_default', (t) => {
  const sgc = getConfig();
  const configuration = getConfig();
  const choicesList = choices(configuration);
  const choicesArray = [];

  Promise.resolve(() => {
    sgc.types.forEach((type) => {
      const emoji = `${type.emoji} ` || '';
      const configType = type.type;
      const description = type.description || '';

      choicesArray.push({
        value: emoji + configType,
        name: `${chalk.bold(configType)} ${description}`,
      });
    }).then(() => {
      t.deepEqual(choicesList, choicesArray);
    });
  });
});

test('check the values of the question object', (t) => {
  const configuration = getConfig();
  const choicesList = choices(configuration);
  const questionsList = questions(choicesList);

  t.deepEqual(typeof questionsList, 'object');
});

test('validate functions in questions', (t) => {
  const configuration = getConfig();
  const choicesList = choices(configuration);
  const questionsList = questions(choicesList);

  t.deepEqual(questionsList[1].validate('input text'), true);
  t.deepEqual(questionsList[1].validate(), 'A commit message is mandatory!');
});
<commit_msg>:white_check_mark: Test: add before and after test<commit_after>import fs from 'fs-extra';
import test from 'ava';
import path from 'path';
import chalk from 'chalk';
import json from 'json-extra';
import os from 'os';
import getConfig from '../lib/getConfig';
import { choices, questions } from '../lib/promptConfig';

const cwd = process.cwd();
const homedir = os.homedir();
const randomString = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10);

let globalExist = false;

// rename global .sgcrc
test.before(() => {
  if (fs.existsSync(path.join(homedir, '.sgcrc'))) {
    globalExist = true;
    fs.renameSync(path.join(homedir, '.sgcrc'), path.join(homedir, `.sgcrc.${randomString}.back`));
  }
});

test.after(() => {
  if (globalExist) {
    fs.renameSync(path.join(homedir, `.sgcrc.${randomString}.back`), path.join(homedir, '.sgcrc'));
  }
});

test('get configuration file equals .sgcrc_default', (t) => {
  t.deepEqual(getConfig(), json.readToObjSync(path.join(cwd, '.sgcrc_default')));
});

test('choices are the same as choices generated from .sgcrc_default', (t) => {
  const sgc = getConfig();
  const configuration = getConfig();
  const choicesList = choices(configuration);
  const choicesArray = [];

  Promise.resolve(() => {
    sgc.types.forEach((type) => {
      const emoji = `${type.emoji} ` || '';
      const configType = type.type;
      const description = type.description || '';

      choicesArray.push({
        value: emoji + configType,
        name: `${chalk.bold(configType)} ${description}`,
      });
    }).then(() => {
      t.deepEqual(choicesList, choicesArray);
    });
  });
});

test('check the values of the question object', (t) => {
  const configuration = getConfig();
  const choicesList = choices(configuration);
  const questionsList = questions(choicesList);

  t.deepEqual(typeof questionsList, 'object');
});

test('validate functions in questions', (t) => {
  const configuration = getConfig();
  const choicesList = choices(configuration);
  const questionsList = questions(choicesList);

  t.deepEqual(questionsList[1].validate('input text'), true);
  t.deepEqual(questionsList[1].validate(), 'A commit message is mandatory!');
});
<|endoftext|>


<commit_before>var expect = require('chai').expect;
var request = require('request');
var crypto = require('crypto');
var async = require('async');
var moment = require('moment');

var pubsub = require('../controllers/pubsub.js').pubsub;
var server = require('../server.js');
var mongo = require('../models/db.js');

var thisNow = moment().unix();
var topic = 'http://test.com';
var topicTitle = 'Test Feed';
var itemTitle = 'This is a test';
var itemStatus = 'Test';
var item2Title = 'This is the second item';
var authorname = 'Testy Authorson';
var response_body = JSON.stringify(
  {
    "title": topicTitle,
    "status": {
      "lastFetch": thisNow,
      "http": 200
    },
    "items": [
      {
        "title": itemTitle,
        "published": thisNow,
        "status": itemStatus,
        "actor": {
          "displayName": authorname,
          "id": authorname
        }
      },
      {
        "title": item2Title,
        "status": itemStatus,
        "actor": {
          "displayName": authorname,
        }
      }
    ]
  }
);
var encrypted_secret = crypto.createHmac("sha1", pubsub.secret).update(topic).digest("hex");
var hub_encryption = crypto.createHmac('sha1', encrypted_secret).update(response_body).digest('hex');

describe('pubsub', function () {
  it('should exist', function () {
    expect(pubsub).to.exist;
  });

  it('should have correct options', function () {
    expect(pubsub.secret).to.equal('supersecret');
    expect(pubsub.format).to.equal('json');
  });
});

describe('authorization', function () {
  before(function (done) {
    server.start(function () {
      done();
    });
  });

  after(function (done) {
    server.close(function () {
      done();
    });
  });

  it('should return 401 - unauthorized (admin page)', function (done) {
    request.get('http://localhost:4000/admin', function (err, response, body) {
      expect(response.statusCode).to.equal(401);
      done();
    });
  });

  it('should return 401 - unauthorized (pending page)', function (done) {
    request.get('http://localhost:4000/admin/pending', function (err, response, body) {
      expect(response.statusCode).to.equal(401);
      done();
    });
  });

  it('should return 401 - unauthorized (subscribe page)', function (done) {
    request.get('http://localhost:4000/admin/subscribe', function (err, response, body) {
      expect(response.statusCode).to.equal(401);
      done();
    });
  });

  it('should return 200 - authorized (admin page)', function (done) {
    var postParams = {
      url: 'http://localhost:4000/admin/',
      auth: {
        user: 'admin',
        pass: 'password'
      }
    }
    request.get(postParams, function (err, response, body) {
      expect(response.statusCode).to.equal(200);
      done();
    });
  });

  it('should return 401 - incorrect authorization (admin page)', function (done) {
    var postParams = {
      url: 'http://localhost:4000/admin',
      auth: {
        user: 'administrator',
        pass: 'password1'
      }
    }
    request.get(postParams, function (err, response, body) {
      expect(response.statusCode).to.equal(401);
      done();
    });
  });

  it('should return 401 - unauthorized (subscribe api)', function (done) {
    var url = 'http://localhost:4000/api/v1/subscribe';

    request.post(url, function (err, response, body) {
      expect(response.statusCode).to.equal(401);
      done();
    });
  });
});

describe('pubsub notification', function () {
  before(function (done) {
    server.start(function () {
      async.series({
        removeFeed: function (callback) {
          mongo.feeds.collection.remove({topic: topic}, function (err, result) {
            if (err) return callback(err);
            return callback(null, result);
          });
        },
        feed: function (callback) {
          mongo.feeds.subscribe(topic, encrypted_secret, function (err, result) {
            if (err) return callback(err);
            return callback(null, result);
          });
        },
        entry: function (callback) {
          mongo.entries.collection.remove({status: 'Test'}, function (err, result) {
            if (err) return callback(err);
            return callback(null, result);
          });
        },
        authors: function (callback) {
          mongo.authors.collection.remove({}, function (err, result) {
            if (err) return callback(err);
            return callback(null, result);
          });
        }
      }, function (err, results) {
        if (err) throw err;
        done();
      });
    });
  });

  after(function (done) {
    server.close(function () {
      done();
    });
  });

  it('should return 400 - no topic', function (done) {
    var options = {
      url: 'http://localhost:4000/pubsubhubbub',
      headers: {
        'link': '<http://pubsubhubbub.appspot.com/>; rel="hub"'
      }
    };

    request.post(options, function (err, res, body) {
      expect(res.statusCode).to.equal(400);
      done();
    });
  });

  it('should return 403 - not subscribed to topic', function (done) {
    var options = {
      url: 'http://localhost:4000/pubsubhubbub',
      headers: {
        'link': '<http://test.com/feed>; rel="self", <http://pubsubhubbub.appspot.com/>; rel="hub"',
      }
    };

    request.post(options, function (err, res, body) {
      expect(res.statusCode).to.equal(403);
      done();
    });
  });

  it('should return 403 - no X-Hub-Signature', function (done) {
    var options = {
      url: 'http://localhost:4000/pubsubhubbub',
      headers: {
        'link': '<http://test.com>; rel="self", <http://pubsubhubbub.appspot.com/>; rel="hub"',
      }
    };

    request.post(options, function (err, res, body) {
      expect(res.statusCode).to.equal(403);
      done();
    });
  });

  it('should return 202 - signature does not match', function (done) {
    var options = {
      url: 'http://localhost:4000/pubsubhubbub',
      headers: {
        'X-Hub-Signature': 'sha1='+hub_encryption,
        'link': '<http://test.com>; rel="self", <http://pubsubhubbub.appspot.com/>; rel="hub"',
      },
      body: response_body + "potentially malicious content"
    };

    request.post(options, function (err, res, body) {
      expect(res.statusCode).to.equal(202);
      done();
    });
  });

  it('should successfully update a feed with new items', function (done) {
    var options = {
      url: 'http://localhost:4000/pubsubhubbub',
      headers: {
        'X-Hub-Signature': 'sha1='+hub_encryption,
        'link': '<http://test.com>; rel="self", <http://pubsubhubbub.appspot.com/>; rel="hub"',
        'Content-Type': 'application/json'
      },
      body: response_body
    };
    var eventFired = false;

    request.post(options, function (err, res, body) {
      expect(res.statusCode, 'response statusCode').to.equal(204);
    });

    pubsub.on('feed_update', function (data) {
      eventFired = true;
      expect(data.topic, 'data topic').to.equal(topic);
      expect(data.feed, 'data feed').to.exist;
      expect(data.headers['content-type'], 'data content-type header').to.equal('application/json');
    });

    setTimeout(function () {
      expect(eventFired, 'event fired').to.equal(true);
      async.series({
        feed: function (callback) {
          mongo.feeds.findOneByTopic(topic, function (err, doc) {
            if (err) return callback(err);
            expect(doc.topic, 'feed topic').to.equal(topic);
            expect(doc.title, 'feed title').to.equal(topicTitle);
            expect(doc.lastFetch, 'feed lastFetch').to.equal(thisNow);
            expect(doc.http, 'feed http').to.equal(200);
            callback(null);
          });
        },
        entry1: function (callback) {
          mongo.entries.collection.findOne({title: itemTitle}, function (err, doc) {
            if (err) return callback(err);
            expect(doc.topic, 'doc1 topic').to.equal(topic);
            expect(doc.title, 'doc1 title').to.equal(itemTitle);
            expect(doc.published, 'doc1 published').to.equal(thisNow);
            expect(doc.status, 'doc1 status').to.equal(itemStatus);
            expect(doc.actor.displayName, 'doc1 author').to.equal('Testy Authorson');
            callback(null);
          });
        },
        entry2: function (callback) {
          mongo.entries.collection.findOne({title: item2Title}, function (err, doc) {
            if (err) return callback(err);
            expect(doc.topic, 'doc2 topic').to.equal(topic);
            expect(doc.title, 'doc2 title').to.equal(item2Title);
            expect(doc.published, 'doc2 published').to.exist;
            expect(doc.status, 'doc2 status').to.equal(itemStatus);
            callback(null);
          });
        },
        author: function (callback) {
          mongo.authors.findOne(authorname, function (err, doc) {
            if (err) return callback(err);
            expect(doc.displayName, 'author DisplayName').to.equal(authorname);
            callback(null);
          });
        },
        authornumber: function (callback) {
          mongo.authors.count(function (err, result) {
            if (err) return callback(err);
            expect(result, 'number of authors').to.equal(1);
            callback(null);
          });
        }
      }, function (err, result) {
        if (err) return done();
        done();
      });
    }, 50);
  });
});<commit_msg>Removed old admin page auth tests<commit_after>var expect = require('chai').expect;
var request = require('request');
var crypto = require('crypto');
var async = require('async');
var moment = require('moment');

var pubsub = require('../controllers/pubsub.js').pubsub;
var server = require('../server.js');
var mongo = require('../models/db.js');

var thisNow = moment().unix();
var topic = 'http://test.com';
var topicTitle = 'Test Feed';
var itemTitle = 'This is a test';
var itemStatus = 'Test';
var item2Title = 'This is the second item';
var authorname = 'Testy Authorson';
var response_body = JSON.stringify(
  {
    "title": topicTitle,
    "status": {
      "lastFetch": thisNow,
      "http": 200
    },
    "items": [
      {
        "title": itemTitle,
        "published": thisNow,
        "status": itemStatus,
        "actor": {
          "displayName": authorname,
          "id": authorname
        }
      },
      {
        "title": item2Title,
        "status": itemStatus,
        "actor": {
          "displayName": authorname,
        }
      }
    ]
  }
);
var encrypted_secret = crypto.createHmac("sha1", pubsub.secret).update(topic).digest("hex");
var hub_encryption = crypto.createHmac('sha1', encrypted_secret).update(response_body).digest('hex');

describe('pubsub', function () {
  it('should exist', function () {
    expect(pubsub).to.exist;
  });

  it('should have correct options', function () {
    expect(pubsub.secret).to.equal('supersecret');
    expect(pubsub.format).to.equal('json');
  });
});

describe('pubsub notification', function () {
  before(function (done) {
    server.start(function () {
      async.series({
        removeFeed: function (callback) {
          mongo.feeds.collection.remove({topic: topic}, function (err, result) {
            if (err) return callback(err);
            return callback(null, result);
          });
        },
        feed: function (callback) {
          mongo.feeds.subscribe(topic, encrypted_secret, function (err, result) {
            if (err) return callback(err);
            return callback(null, result);
          });
        },
        entry: function (callback) {
          mongo.entries.collection.remove({status: 'Test'}, function (err, result) {
            if (err) return callback(err);
            return callback(null, result);
          });
        },
        authors: function (callback) {
          mongo.authors.collection.remove({}, function (err, result) {
            if (err) return callback(err);
            return callback(null, result);
          });
        }
      }, function (err, results) {
        if (err) throw err;
        done();
      });
    });
  });

  after(function (done) {
    server.close(function () {
      done();
    });
  });

  it('should return 400 - no topic', function (done) {
    var options = {
      url: 'http://localhost:4000/pubsubhubbub',
      headers: {
        'link': '<http://pubsubhubbub.appspot.com/>; rel="hub"'
      }
    };

    request.post(options, function (err, res, body) {
      expect(res.statusCode).to.equal(400);
      done();
    });
  });

  it('should return 403 - not subscribed to topic', function (done) {
    var options = {
      url: 'http://localhost:4000/pubsubhubbub',
      headers: {
        'link': '<http://test.com/feed>; rel="self", <http://pubsubhubbub.appspot.com/>; rel="hub"',
      }
    };

    request.post(options, function (err, res, body) {
      expect(res.statusCode).to.equal(403);
      done();
    });
  });

  it('should return 403 - no X-Hub-Signature', function (done) {
    var options = {
      url: 'http://localhost:4000/pubsubhubbub',
      headers: {
        'link': '<http://test.com>; rel="self", <http://pubsubhubbub.appspot.com/>; rel="hub"',
      }
    };

    request.post(options, function (err, res, body) {
      expect(res.statusCode).to.equal(403);
      done();
    });
  });

  it('should return 202 - signature does not match', function (done) {
    var options = {
      url: 'http://localhost:4000/pubsubhubbub',
      headers: {
        'X-Hub-Signature': 'sha1='+hub_encryption,
        'link': '<http://test.com>; rel="self", <http://pubsubhubbub.appspot.com/>; rel="hub"',
      },
      body: response_body + "potentially malicious content"
    };

    request.post(options, function (err, res, body) {
      expect(res.statusCode).to.equal(202);
      done();
    });
  });

  it('should successfully update a feed with new items', function (done) {
    var options = {
      url: 'http://localhost:4000/pubsubhubbub',
      headers: {
        'X-Hub-Signature': 'sha1='+hub_encryption,
        'link': '<http://test.com>; rel="self", <http://pubsubhubbub.appspot.com/>; rel="hub"',
        'Content-Type': 'application/json'
      },
      body: response_body
    };
    var eventFired = false;

    request.post(options, function (err, res, body) {
      expect(res.statusCode, 'response statusCode').to.equal(204);
    });

    pubsub.on('feed_update', function (data) {
      eventFired = true;
      expect(data.topic, 'data topic').to.equal(topic);
      expect(data.feed, 'data feed').to.exist;
      expect(data.headers['content-type'], 'data content-type header').to.equal('application/json');
    });

    setTimeout(function () {
      expect(eventFired, 'event fired').to.equal(true);
      async.series({
        feed: function (callback) {
          mongo.feeds.findOneByTopic(topic, function (err, doc) {
            if (err) return callback(err);
            expect(doc.topic, 'feed topic').to.equal(topic);
            expect(doc.title, 'feed title').to.equal(topicTitle);
            expect(doc.lastFetch, 'feed lastFetch').to.equal(thisNow);
            expect(doc.http, 'feed http').to.equal(200);
            callback(null);
          });
        },
        entry1: function (callback) {
          mongo.entries.collection.findOne({title: itemTitle}, function (err, doc) {
            if (err) return callback(err);
            expect(doc.topic, 'doc1 topic').to.equal(topic);
            expect(doc.title, 'doc1 title').to.equal(itemTitle);
            expect(doc.published, 'doc1 published').to.equal(thisNow);
            expect(doc.status, 'doc1 status').to.equal(itemStatus);
            expect(doc.actor.displayName, 'doc1 author').to.equal('Testy Authorson');
            callback(null);
          });
        },
        entry2: function (callback) {
          mongo.entries.collection.findOne({title: item2Title}, function (err, doc) {
            if (err) return callback(err);
            expect(doc.topic, 'doc2 topic').to.equal(topic);
            expect(doc.title, 'doc2 title').to.equal(item2Title);
            expect(doc.published, 'doc2 published').to.exist;
            expect(doc.status, 'doc2 status').to.equal(itemStatus);
            callback(null);
          });
        },
        author: function (callback) {
          mongo.authors.findOne(authorname, function (err, doc) {
            if (err) return callback(err);
            expect(doc.displayName, 'author DisplayName').to.equal(authorname);
            callback(null);
          });
        },
        authornumber: function (callback) {
          mongo.authors.count(function (err, result) {
            if (err) return callback(err);
            expect(result, 'number of authors').to.equal(1);
            callback(null);
          });
        }
      }, function (err, result) {
        if (err) return done();
        done();
      });
    }, 50);
  });
});<|endoftext|>


<commit_before>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import Box from '../box';
import cx from 'classnames';
import theme from './theme.css';
import omit from 'lodash.omit';

class IconTab extends PureComponent {
  static propTypes = {
    active: PropTypes.bool,
    children: PropTypes.node.isRequired,
    className: PropTypes.string,
    counter: PropTypes.node,
    element: PropTypes.node,
    icon: PropTypes.node.isRequired,
    onClick: PropTypes.func,
  };

  static defaultProps = {
    element: 'a',
    active: false,
  };

  constructor() {
    super(...arguments);
    this.handleClick = ::this.handleClick;
  }

  handleClick(event) {
    if (this.props.onClick) {
      this.props.onClick(event);
    }
    if (event.pageX !== 0 && event.pageY !== 0) {
      this.blur();
    }
  }

  blur() {
    if (this.tabNode) {
      this.tabNode.getNode().blur();
    }
  }

  render() {
    const { active, className, counter = null, icon, ...others } = this.props;
    const classNames = cx(theme['icon-tab'], { [theme['is-active']]: active }, className);

    const rest = omit(others, ['onClick']);

    return (
      <Box
        data-teamleader-ui="icon-tab"
        className={classNames}
        marginHorizontal={3}
        paddingHorizontal={3}
        paddingVertical={4}
        ref={node => {
          this.tabNode = node;
        }}
        onClick={this.handleClick}
        {...rest}
      >
        {
          React.cloneElement(icon, { element: "span" })
        }
        {counter && React.cloneElement(counter, { className: theme['counter'] })}
      </Box>
    );
  }
}

export default IconTab;
<commit_msg>:rotating_light: Format<commit_after>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import Box from '../box';
import cx from 'classnames';
import theme from './theme.css';
import omit from 'lodash.omit';

class IconTab extends PureComponent {
  static propTypes = {
    active: PropTypes.bool,
    children: PropTypes.node.isRequired,
    className: PropTypes.string,
    counter: PropTypes.node,
    element: PropTypes.node,
    icon: PropTypes.node.isRequired,
    onClick: PropTypes.func,
  };

  static defaultProps = {
    element: 'a',
    active: false,
  };

  constructor() {
    super(...arguments);
    this.handleClick = ::this.handleClick;
  }

  handleClick(event) {
    if (this.props.onClick) {
      this.props.onClick(event);
    }
    if (event.pageX !== 0 && event.pageY !== 0) {
      this.blur();
    }
  }

  blur() {
    if (this.tabNode) {
      this.tabNode.getNode().blur();
    }
  }

  render() {
    const { active, className, counter = null, icon, ...others } = this.props;
    const classNames = cx(theme['icon-tab'], { [theme['is-active']]: active }, className);

    const rest = omit(others, ['onClick']);

    return (
      <Box
        data-teamleader-ui="icon-tab"
        className={classNames}
        marginHorizontal={3}
        paddingHorizontal={3}
        paddingVertical={4}
        ref={node => {
          this.tabNode = node;
        }}
        onClick={this.handleClick}
        {...rest}
      >
        {React.cloneElement(icon, { element: 'span' })}
        {counter && React.cloneElement(counter, { className: theme['counter'] })}
      </Box>
    );
  }
}

export default IconTab;
<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2017  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('3.3.0');
		this.setClientTag('node:17-08-05');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2017  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('3.3.0');
		this.setClientTag('node:17-08-06');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>


<commit_before>import {takeLatest} from 'redux-saga';
import {call, put} from 'redux-saga/effects';
import Apis from 'shared/api_client/ApiInstances';
import MarketReducer from './MarketReducer';
import {getAccount} from './SagaShared';

export const marketWatches = [watchLocationChange, watchUserLogin, watchMarketUpdate];

const wait = ms => (
    new Promise(resolve => {
        setTimeout(() => resolve(), ms)
    }))

let polling = false
let active_user = null
let last_trade = null

export function* fetchMarket(location_change_action) {
    const {pathname} = location_change_action.payload;
    if (pathname && pathname != "/market") {
        polling = false
        return
    }

    if(polling == true) return
    polling = true

    while(polling) {

        try {
            const db_api = Apis.instance().db_api;
            const market_api = Apis.instance().market;

            const state = yield call([db_api, db_api.exec], 'get_order_book', [500]);
            yield put(MarketReducer.actions.receiveOrderbook(state));

            let trades;
            if(last_trade == null ) {
                trades = yield call([market_api, market_api.exec], 'get_recent_trades', [25]);
                yield put(MarketReducer.actions.receiveTradeHistory(trades));
            } else {
                let start = last_trade.toISOString().slice(0, -5)
                trades = yield call([market_api, market_api.exec], 'get_trade_history', [start, "1969-12-31T23:59:59", 1000]);
                trades = trades.reverse()
                yield put(MarketReducer.actions.appendTradeHistory(trades));
            }
            if(trades.length > 0) {
              last_trade = new Date((new Date(Date.parse(trades[0]['date']))).getTime() + 1000)
            }

            const state3 = yield call([market_api, market_api.exec], 'get_ticker');
            yield put(MarketReducer.actions.receiveTicker(state3));
        } catch (error) {
            console.error('~~ Saga fetchMarket error ~~>', error);
            yield put({type: 'global/STEEM_API_ERROR', error: error.message});
        }

        yield call(wait, 3000);
    }
}

export function* fetchOpenOrders(set_user_action) {
    const {username} = set_user_action.payload

    try {
        const db_api = Apis.instance().db_api;
        const state = yield call([db_api, db_api.exec], 'get_open_orders', [username]);
        yield put(MarketReducer.actions.receiveOpenOrders(state));
        yield call(getAccount, username, true);
    } catch (error) {
        console.error('~~ Saga fetchOpenOrders error ~~>', error);
        yield put({type: 'global/STEEM_API_ERROR', error: error.message});
    }
}

export function* reloadMarket(reload_action) {
    yield fetchMarket(reload_action);
    yield fetchOpenOrders(reload_action);
}

export function* watchUserLogin() {
    yield* takeLatest('user/SET_USER', fetchOpenOrders);
}

export function* watchLocationChange() {
    yield* takeLatest('@@router/LOCATION_CHANGE', fetchMarket);
}

export function* watchMarketUpdate() {
    yield* takeLatest('market/UPDATE_MARKET', reloadMarket);
}
<commit_msg>Convert market api calls steem-js. #1119<commit_after>import {takeLatest} from 'redux-saga';
import {call, put} from 'redux-saga/effects';
import MarketReducer from './MarketReducer';
import {getAccount} from './SagaShared';
import {api} from 'steem';

export const marketWatches = [watchLocationChange, watchUserLogin, watchMarketUpdate];

const wait = ms => (
    new Promise(resolve => {
        setTimeout(() => resolve(), ms)
    }))

let polling = false
let active_user = null
let last_trade = null

export function* fetchMarket(location_change_action) {
    const {pathname} = location_change_action.payload;
    if (pathname && pathname != "/market") {
        polling = false
        return
    }

    if(polling == true) return
    polling = true

    while(polling) {

        try {
            const state = yield call([api, api.getOrderBookAsync], 500);
            yield put(MarketReducer.actions.receiveOrderbook(state));

            let trades;
            if(last_trade == null ) {
                trades = yield call([api, api.getRecentTradesAsync], 25);
                yield put(MarketReducer.actions.receiveTradeHistory(trades));
            } else {
                let start = last_trade.toISOString().slice(0, -5)
                trades = yield call([api, api.getTradeHistoryAsync], start, "1969-12-31T23:59:59", 1000);
                trades = trades.reverse()
                yield put(MarketReducer.actions.appendTradeHistory(trades));
            }
            if(trades.length > 0) {
              last_trade = new Date((new Date(Date.parse(trades[0]['date']))).getTime() + 1000)
            }

            const state3 = yield call([api, api.getTickerAsync]);
            yield put(MarketReducer.actions.receiveTicker(state3));
        } catch (error) {
            console.error('~~ Saga fetchMarket error ~~>', error);
            yield put({type: 'global/STEEM_API_ERROR', error: error.message});
        }

        yield call(wait, 3000);
    }
}

export function* fetchOpenOrders(set_user_action) {
    const {username} = set_user_action.payload

    try {
        const state = yield call([api, api.getOpenOrdersAsync], username);
        yield put(MarketReducer.actions.receiveOpenOrders(state));
        yield call(getAccount, username, true);
    } catch (error) {
        console.error('~~ Saga fetchOpenOrders error ~~>', error);
        yield put({type: 'global/STEEM_API_ERROR', error: error.message});
    }
}

export function* reloadMarket(reload_action) {
    yield fetchMarket(reload_action);
    yield fetchOpenOrders(reload_action);
}

export function* watchUserLogin() {
    yield* takeLatest('user/SET_USER', fetchOpenOrders);
}

export function* watchLocationChange() {
    yield* takeLatest('@@router/LOCATION_CHANGE', fetchMarket);
}

export function* watchMarketUpdate() {
    yield* takeLatest('market/UPDATE_MARKET', reloadMarket);
}
<|endoftext|>


<commit_before>'use strict';
const path = require('path');

const electron = require('electron');

const { ipcRenderer, remote } = electron;

const { Tray, Menu, nativeImage, BrowserWindow } = remote;

const APP_ICON = path.join(__dirname, '../../resources/tray', 'tray');

const ConfigUtil = require(__dirname + '/utils/config-util.js');

const iconPath = () => {
	if (process.platform === 'linux') {
		return APP_ICON + 'linux.png';
	}
	return APP_ICON + (process.platform === 'win32' ? 'win.ico' : 'osx.png');
};

let unread = 0;

const trayIconSize = () => {
	switch (process.platform) {
		case 'darwin':
			return 20;
		case 'win32':
			return 100;
		case 'linux':
			return 100;
		default: return 80;
	}
};

//  Default config for Icon we might make it OS specific if needed like the size
const config = {
	pixelRatio: window.devicePixelRatio,
	unreadCount: 0,
	showUnreadCount: true,
	unreadColor: '#000000',
	readColor: '#000000',
	unreadBackgroundColor: '#B9FEEA',
	readBackgroundColor: '#B9FEEA',
	size: trayIconSize(),
	thick: process.platform === 'win32'
};

const renderCanvas = function (arg) {
	config.unreadCount = arg;

	return new Promise(resolve => {
		const SIZE = config.size * config.pixelRatio;
		const PADDING = SIZE * 0.05;
		const CENTER = SIZE / 2;
		const HAS_COUNT = config.showUnreadCount && config.unreadCount;
		const color = config.unreadCount ? config.unreadColor : config.readColor;
		const backgroundColor = config.unreadCount ? config.unreadBackgroundColor : config.readBackgroundColor;

		const canvas = document.createElement('canvas');
		canvas.width = SIZE;
		canvas.height = SIZE;
		const ctx = canvas.getContext('2d');

		// Circle
		// If (!config.thick || config.thick && HAS_COUNT) {
		ctx.beginPath();
		ctx.arc(CENTER, CENTER, (SIZE / 2) - PADDING, 0, 2 * Math.PI, false);
		ctx.fillStyle = backgroundColor;
		ctx.fill();
		ctx.lineWidth = SIZE / (config.thick ? 10 : 20);
		ctx.strokeStyle = backgroundColor;
		ctx.stroke();
		// Count or Icon
		if (HAS_COUNT) {
			ctx.fillStyle = color;
			ctx.textAlign = 'center';
			if (config.unreadCount > 99) {
				ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.4}px Helvetica`;
				ctx.fillText('99+', CENTER, CENTER + (SIZE * 0.15));
			} else if (config.unreadCount < 10) {
				ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.5}px Helvetica`;
				ctx.fillText(config.unreadCount, CENTER, CENTER + (SIZE * 0.20));
			} else {
				ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.5}px Helvetica`;
				ctx.fillText(config.unreadCount, CENTER, CENTER + (SIZE * 0.15));
			}

			resolve(canvas);
		}
	});
};
/**
 * Renders the tray icon as a native image
 * @param arg: Unread count
 * @return the native image
 */
const renderNativeImage = function (arg) {
	return Promise.resolve()
		.then(() => renderCanvas(arg))
		.then(canvas => {
			const pngData = nativeImage.createFromDataURL(canvas.toDataURL('image/png')).toPNG();
			return Promise.resolve(nativeImage.createFromBuffer(pngData, config.pixelRatio));
		});
};

function sendAction(action) {
	const win = BrowserWindow.getAllWindows()[0];

	if (process.platform === 'darwin') {
		win.restore();
	}

	win.webContents.send(action);
}

const createTray = function () {
	window.tray = new Tray(iconPath());
	const contextMenu = Menu.buildFromTemplate([{
		label: 'About',
		click() {
			// We need to focus the main window first
			ipcRenderer.send('focus-app');
			sendAction('open-about');
		}
	},
	{
		label: 'Focus',
		click() {
			ipcRenderer.send('focus-app');
		}
	},
	{
		label: 'Settings',
		click() {
			ipcRenderer.send('focus-app');
			sendAction('open-settings');
		}
	},
	{
		label: 'Quit',
		click() {
			ipcRenderer.send('quit-app');
		}
	}
	]);
	window.tray.setContextMenu(contextMenu);
	if (process.platform === 'linux' || process.platform === 'win32') {
		window.tray.on('click', () => {
			ipcRenderer.send('toggle-app');
		});
	}
};

ipcRenderer.on('destroytray', event => {
	if (!window.tray) {
		return;
	}

	window.tray.destroy();
	if (window.tray.isDestroyed()) {
		window.tray = null;
	} else {
		throw new Error('Tray icon not properly destroyed.');
	}

	return event;
});

ipcRenderer.on('tray', (event, arg) => {
	if (!window.tray) {
		return;
	}
	// We don't want to create tray from unread messages on macOS since it already has dock badges.
	if (process.platform === 'linux' || process.platform === 'win32') {
		if (arg === 0) {
			unread = arg;
			window.tray.setImage(iconPath());
			window.tray.setToolTip('No unread messages');
		} else {
			unread = arg;
			renderNativeImage(arg).then(image => {
				window.tray.setImage(image);
				window.tray.setToolTip(arg + ' unread messages');
			});
		}
	}
});

function toggleTray() {
	let state;
	if (window.tray) {
		state = false;
		window.tray.destroy();
		if (window.tray.isDestroyed()) {
			window.tray = null;
		}
		ConfigUtil.setConfigItem('trayIcon', false);
	} else {
		state = true;
		createTray();
		if (process.platform === 'linux' || process.platform === 'win32') {
			renderNativeImage(unread).then(image => {
				window.tray.setImage(image);
				window.tray.setToolTip(unread + ' unread messages');
			});
		}
		ConfigUtil.setConfigItem('trayIcon', true);
	}
	const selector = 'webview:not([class*=disabled])';
	const webview = document.querySelector(selector);
	const webContents = webview.getWebContents();
	webContents.send('toggletray', state);
}

ipcRenderer.on('toggletray', toggleTray);

if (ConfigUtil.getConfigItem('trayIcon', true)) {
	createTray();
}
<commit_msg>tray: Add a separator in tray before quit item.<commit_after>'use strict';
const path = require('path');

const electron = require('electron');

const { ipcRenderer, remote } = electron;

const { Tray, Menu, nativeImage, BrowserWindow } = remote;

const APP_ICON = path.join(__dirname, '../../resources/tray', 'tray');

const ConfigUtil = require(__dirname + '/utils/config-util.js');

const iconPath = () => {
	if (process.platform === 'linux') {
		return APP_ICON + 'linux.png';
	}
	return APP_ICON + (process.platform === 'win32' ? 'win.ico' : 'osx.png');
};

let unread = 0;

const trayIconSize = () => {
	switch (process.platform) {
		case 'darwin':
			return 20;
		case 'win32':
			return 100;
		case 'linux':
			return 100;
		default: return 80;
	}
};

//  Default config for Icon we might make it OS specific if needed like the size
const config = {
	pixelRatio: window.devicePixelRatio,
	unreadCount: 0,
	showUnreadCount: true,
	unreadColor: '#000000',
	readColor: '#000000',
	unreadBackgroundColor: '#B9FEEA',
	readBackgroundColor: '#B9FEEA',
	size: trayIconSize(),
	thick: process.platform === 'win32'
};

const renderCanvas = function (arg) {
	config.unreadCount = arg;

	return new Promise(resolve => {
		const SIZE = config.size * config.pixelRatio;
		const PADDING = SIZE * 0.05;
		const CENTER = SIZE / 2;
		const HAS_COUNT = config.showUnreadCount && config.unreadCount;
		const color = config.unreadCount ? config.unreadColor : config.readColor;
		const backgroundColor = config.unreadCount ? config.unreadBackgroundColor : config.readBackgroundColor;

		const canvas = document.createElement('canvas');
		canvas.width = SIZE;
		canvas.height = SIZE;
		const ctx = canvas.getContext('2d');

		// Circle
		// If (!config.thick || config.thick && HAS_COUNT) {
		ctx.beginPath();
		ctx.arc(CENTER, CENTER, (SIZE / 2) - PADDING, 0, 2 * Math.PI, false);
		ctx.fillStyle = backgroundColor;
		ctx.fill();
		ctx.lineWidth = SIZE / (config.thick ? 10 : 20);
		ctx.strokeStyle = backgroundColor;
		ctx.stroke();
		// Count or Icon
		if (HAS_COUNT) {
			ctx.fillStyle = color;
			ctx.textAlign = 'center';
			if (config.unreadCount > 99) {
				ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.4}px Helvetica`;
				ctx.fillText('99+', CENTER, CENTER + (SIZE * 0.15));
			} else if (config.unreadCount < 10) {
				ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.5}px Helvetica`;
				ctx.fillText(config.unreadCount, CENTER, CENTER + (SIZE * 0.20));
			} else {
				ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.5}px Helvetica`;
				ctx.fillText(config.unreadCount, CENTER, CENTER + (SIZE * 0.15));
			}

			resolve(canvas);
		}
	});
};
/**
 * Renders the tray icon as a native image
 * @param arg: Unread count
 * @return the native image
 */
const renderNativeImage = function (arg) {
	return Promise.resolve()
		.then(() => renderCanvas(arg))
		.then(canvas => {
			const pngData = nativeImage.createFromDataURL(canvas.toDataURL('image/png')).toPNG();
			return Promise.resolve(nativeImage.createFromBuffer(pngData, config.pixelRatio));
		});
};

function sendAction(action) {
	const win = BrowserWindow.getAllWindows()[0];

	if (process.platform === 'darwin') {
		win.restore();
	}

	win.webContents.send(action);
}

const createTray = function () {
	window.tray = new Tray(iconPath());
	const contextMenu = Menu.buildFromTemplate([{
		label: 'About',
		click() {
			// We need to focus the main window first
			ipcRenderer.send('focus-app');
			sendAction('open-about');
		}
	},
	{
		label: 'Focus',
		click() {
			ipcRenderer.send('focus-app');
		}
	},
	{
		label: 'Settings',
		click() {
			ipcRenderer.send('focus-app');
			sendAction('open-settings');
		}
	},
	{
		type: 'separator'
	},
	{
		label: 'Quit',
		click() {
			ipcRenderer.send('quit-app');
		}
	}
	]);
	window.tray.setContextMenu(contextMenu);
	if (process.platform === 'linux' || process.platform === 'win32') {
		window.tray.on('click', () => {
			ipcRenderer.send('toggle-app');
		});
	}
};

ipcRenderer.on('destroytray', event => {
	if (!window.tray) {
		return;
	}

	window.tray.destroy();
	if (window.tray.isDestroyed()) {
		window.tray = null;
	} else {
		throw new Error('Tray icon not properly destroyed.');
	}

	return event;
});

ipcRenderer.on('tray', (event, arg) => {
	if (!window.tray) {
		return;
	}
	// We don't want to create tray from unread messages on macOS since it already has dock badges.
	if (process.platform === 'linux' || process.platform === 'win32') {
		if (arg === 0) {
			unread = arg;
			window.tray.setImage(iconPath());
			window.tray.setToolTip('No unread messages');
		} else {
			unread = arg;
			renderNativeImage(arg).then(image => {
				window.tray.setImage(image);
				window.tray.setToolTip(arg + ' unread messages');
			});
		}
	}
});

function toggleTray() {
	let state;
	if (window.tray) {
		state = false;
		window.tray.destroy();
		if (window.tray.isDestroyed()) {
			window.tray = null;
		}
		ConfigUtil.setConfigItem('trayIcon', false);
	} else {
		state = true;
		createTray();
		if (process.platform === 'linux' || process.platform === 'win32') {
			renderNativeImage(unread).then(image => {
				window.tray.setImage(image);
				window.tray.setToolTip(unread + ' unread messages');
			});
		}
		ConfigUtil.setConfigItem('trayIcon', true);
	}
	const selector = 'webview:not([class*=disabled])';
	const webview = document.querySelector(selector);
	const webContents = webview.getWebContents();
	webContents.send('toggletray', state);
}

ipcRenderer.on('toggletray', toggleTray);

if (ConfigUtil.getConfigItem('trayIcon', true)) {
	createTray();
}
<|endoftext|>


<commit_before>can.Control("GGRC.Controllers.TreeFilter", {

}, {

  init : function() {
    var parent_control;
    this._super && this._super.apply(this, arguments);
    this.options.states = new can.Observe();
    parent_control = this.element.closest(".cms_controllers_tree_view").control();
    parent_control && parent_control.options.attr("states", this.options.states);
    this.on();
  }

  , "input, select change" : function(el, ev) {
    // Convert '.' to '__' ('.' will cause can.Observe to try to update a path instead of just a key)
    var name = el.attr("name").replace(/\./g, '__');
    if(el.is(".hasDatepicker")) {
      this.options.states.attr(name, moment(el.val(), "MM/DD/YYYY"));
    } else {
      this.options.states.attr(name, el.val());
    }
    ev.stopPropagation();
  }

  , "input[data-lookup] focus" : function(el, ev) {
    this.autocomplete(el);
  }

  , autocomplete : function(el) {
    $.cms_autocomplete.call(this, el);
  }

  , autocomplete_select : function(el, event, ui) {
    setTimeout(function(){
      el.val(ui.item.name ? ui.item.name : ui.item.email, ui.item);
      el.trigger('change');
    }, 0);
  }

  , "{states} change" : function(states) {
    var that = this;
    this.element
    .closest(".tree-structure")
    .children(":has(> [data-model],:data(model))").each(function(i, el) {
      var model = $(el).children("[data-model],:data(model)").data("model");
      if(can.reduce(Object.keys(states._data), function(st, key) {
        var val = states[key]
        , test = that.resolve_object(model, key.replace(/__/g, '.'));

        if(val && val.isAfter) {
          if(!test || !moment(test).isAfter(val)) {
            return false;
          } else {
            return st;
          }
        } else if(val && (!test || !~test.toUpperCase().indexOf(val.toUpperCase()))) {
          return false;
        } else {
          return st;
        }
      }, true)) {
        $(el).show();
      } else {
        $(el).hide();
      }
    });
  }

  , resolve_object : function(obj, path) {
    path = path.split(".");
    can.each(path, function(prop) {
      // If the name is blank, use email
      if (prop === 'name' && obj.attr && (!obj.attr(prop) || !obj.attr(prop).trim()) && obj.attr('email') && obj.attr('email').trim()) {
        prop = 'email';
      }
      obj = obj.attr ? obj.attr(prop) : obj.prop;
      obj = obj && obj.reify ? obj.reify() : obj;
      return obj != null; //stop iterating in case of null/undefined.
    });
    return obj;
  }

  //this controller is used in sticky headers which clone the original element.
  // It should only be destroyed when the original element is destroyed, not any clone.
  , destroy : function(el, ev) {
    var sticky;
    if(this.element.is(el)) {
      this._super.apply(this, arguments);
    } else if((sticky = this.element.data("sticky")) && el.is(sticky.clone)) {
      delete sticky.clone;
    }
  }

});
<commit_msg>Correct the Boolean expression for on-or-after filter.<commit_after>can.Control("GGRC.Controllers.TreeFilter", {

}, {

  init : function() {
    var parent_control;
    this._super && this._super.apply(this, arguments);
    this.options.states = new can.Observe();
    parent_control = this.element.closest(".cms_controllers_tree_view").control();
    parent_control && parent_control.options.attr("states", this.options.states);
    this.on();
  }

  , "input, select change" : function(el, ev) {
    // Convert '.' to '__' ('.' will cause can.Observe to try to update a path instead of just a key)
    var name = el.attr("name").replace(/\./g, '__');
    if(el.is(".hasDatepicker")) {
      this.options.states.attr(name, moment(el.val(), "MM/DD/YYYY"));
    } else {
      this.options.states.attr(name, el.val());
    }
    ev.stopPropagation();
  }

  , "input[data-lookup] focus" : function(el, ev) {
    this.autocomplete(el);
  }

  , autocomplete : function(el) {
    $.cms_autocomplete.call(this, el);
  }

  , autocomplete_select : function(el, event, ui) {
    setTimeout(function(){
      el.val(ui.item.name ? ui.item.name : ui.item.email, ui.item);
      el.trigger('change');
    }, 0);
  }

  , "{states} change" : function(states) {
    var that = this;
    this.element
    .closest(".tree-structure")
    .children(":has(> [data-model],:data(model))").each(function(i, el) {
      var model = $(el).children("[data-model],:data(model)").data("model");
      if(can.reduce(Object.keys(states._data), function(st, key) {
        var val = states[key]
        , test = that.resolve_object(model, key.replace(/__/g, '.'));

        if(val && val.isAfter) {
          if(!test || moment(test).isBefore(val)) {
            return false;
          } else {
            return st;
          }
        } else if(val && (!test || !~test.toUpperCase().indexOf(val.toUpperCase()))) {
          return false;
        } else {
          return st;
        }
      }, true)) {
        $(el).show();
      } else {
        $(el).hide();
      }
    });
  }

  , resolve_object : function(obj, path) {
    path = path.split(".");
    can.each(path, function(prop) {
      // If the name is blank, use email
      if (prop === 'name' && obj.attr && (!obj.attr(prop) || !obj.attr(prop).trim()) && obj.attr('email') && obj.attr('email').trim()) {
        prop = 'email';
      }
      obj = obj.attr ? obj.attr(prop) : obj.prop;
      obj = obj && obj.reify ? obj.reify() : obj;
      return obj != null; //stop iterating in case of null/undefined.
    });
    return obj;
  }

  //this controller is used in sticky headers which clone the original element.
  // It should only be destroyed when the original element is destroyed, not any clone.
  , destroy : function(el, ev) {
    var sticky;
    if(this.element.is(el)) {
      this._super.apply(this, arguments);
    } else if((sticky = this.element.data("sticky")) && el.is(sticky.clone)) {
      delete sticky.clone;
    }
  }

});
<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2020  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('15.15.0');
		this.setClientTag('node:20-01-12');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2020  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('15.15.0');
		this.setClientTag('node:20-01-13');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>