<commit_before>///////////////////////////////////////////////////////////////// Library Setup:

var TelegramBot = require('node-telegram-bot-api');
var fs = require('fs');
var exec = require('child_process').exec;
var cron = require('node-cron');

//////////////////////////////////////////////// Load "Ricecab Bot" Information:

var token = '216808904:AAFqAjnnVVpHmKU4ZsExIMNuUdZX8R49YSQ';
var bot = new TelegramBot(token, {polling: true});
var ricecab_id = -116496721;
var bank_acc = '12-3086-0261060-00';
var path = '/home/pi/ricecab_bot/';

/////////////////////////////////////////////////////// Load "User Information":

var users = [
    {id : 133607928, cost: 2.52}, // Evan Lin
    {id : 177677828, cost: 0.48}, // Honour Carmichael
    {id : 177893563, cost: 1.52}, // Carl Velasco
    {id : 187936081, cost: 2.52}, // Amy Lai
    {id : 199377811, cost: 1.21}, // Vincent Wolfgramm-Russel
    {id : 197336637, cost: 2.52}  // Jay Shen
];

function uget_index(id) {
    for (var i = 0; i < users.length; i++) {
        if (users[i].id === id) {return i;}
    }
    return 0;
}

//////////////////////////////////////////////// "Ricecab Bot" Logic Definition:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/checkin"

bot.onText(/\/checkin/, function(msg, match) {
    var chatId = msg.chat.id;
    var userName = msg.from.first_name + ' ' + msg.from.last_name;
    var userId = msg.from.id;
    var timeStamp = msg.date;

    // FIND MONTHLY SUM >>
    var tripcost = users[uget_index(userId)].cost;
    var cost_sum = get_total_cost(path, userId) + tripcost; // costsum after checkin.
    var n_rides = get_n_rides(path, userId) + 1; // Number of rides after checkin.
    bot.sendMessage(userId, n_rides);

    // DATA STRING >>
    var data = '['
    + 'CHECKIN:"' + timeStamp + '"'
    + ', NAME:"' + userName + '"'
    + ', ID:"' + userId + '"'
    + ', COST:"' + tripcost + '"'
    + ', MONTHLY_SUM:"' + cost_sum + '"'
    + ']\n';

    // FILE IO >>
    // Make Stats File.
    var l1 = "NAME: " + userName + ", ";
    var l2 = "RIDES: " + n_rides + ", ";
    var l3 = "SUM: $" + cost_sum + "\n";

    fs.writeFile(path + 'stats/' + userId + '.txt', l1 + l2 + l3, function(err) {
        if(err) {
            bot.sendMessage(chatId, "ERROR: '/checkin' stats cannot be compiled.");
            console.log(chatId + " ERROR: '/checkin' stats cannot be compiled.");
        }
    });

    // Append to Log File.
    fs.appendFile(path + 'logs/' + userId + '.txt', data, function(err) {
        if(err) {
            bot.sendMessage(chatId, "ERROR: '/checkin' request error.");
            console.log(chatId + " ERROR: '/checkin' request error.");
        }

        // PREPARE PERSONAL MESSAGE >>
        var checkin_msg = "CHECKIN SUCCESSFUL at '" + timeStamp + "'.\n"
            + "Name: " + userName + ", Cost: $" + tripcost + "\n"
            + "Run /stats for more details.";
        bot.sendMessage(chatId, checkin_msg);

        // PREPARE GLOBAL MESSAGE >>
        bot.sendMessage(ricecab_id, userName + " has checked in.");
    });
    console.log(data); // CONSOLE LOG.

});

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/info"
bot.onText(/\/info/, function(msg, match) {
    var chatId = msg.chat.id;

    fs.readFile(path + 'INFO', function(err, data) {
        if (err) {
            bot.sendMessage(chatId, "ERROR: '/info' request has issues.");
            console.log(chatId + " ERROR: '/info' request has issues.");
        }
        bot.sendMessage(chatId, data.toString());
        console.log("[INFO request on " + chatId + "]");
    });
});

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/stats"
bot.onText(/\/stats/, function(msg, match) {

    var chatId = msg.chat.id;
    var userName = msg.from.first_name + ' ' + msg.from.last_name;
    var userId = msg.from.id;

    // Attempt to refresh stats.
    for (var i = 0; i < users.length; i++) {

    }

    // Output Stats >>

    var l0 = "** STATS **\n";

    exec('cat ' + path + 'stats/*', function(err, file_data) {
        if (err) {
            bot.sendMessage(chatId, l0 + "Nothing to show.");
        } else {
            bot.sendMessage(chatId, l0 + file_data.toString());
        }
        console.log("[STATS request on " + chatId + "]");
    });
});

///////////////////////////////////////////////////////// ADMINISTRATOR COMMANDS

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/\"
bot.onText(/\/go/, function(msg, match) {
    var userName = msg.from.first_name + ' ' + msg.from.last_name;
    if (msg.from.id === 133607928) {
        bot.sendMessage(ricecab_id, "Evan is on his way to the car now!");
        console.log("[GO request by " + userName + ": APPROVED]");
    } else {
        console.log("[GO request by " + userName + ": REJECTED]");
    }
});

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/reset"
bot.onText(/\/reset/, function(msg, match) {
    var userName = msg.from.first_name + ' ' + msg.from.last_name;
    if (msg.from.id === 133607928) {
        reset_all();
        console.log("[RESET request by " + userName + ": APPROVED]");
    } else {
        console.log("[RESET request by " + userName + ": REJECTED]");
    }
});

//////////////////////////////////////////////////////////////////////////// FUN

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/photo"
bot.onText(/\/what_is_evan_doing/, function(msg, match) {
    var chatId = msg.chat.id;
    var userName = msg.from.first_name + ' ' + msg.from.last_name;
    var userId = msg.from.id;
    var timeStamp = new Date();

    if (msg.chat.id !== ricecab_id) {
        access_denied( '/photo', userName, userId, chatId, timeStamp);
    } else {
        access_granted( '/photo', userName, userId, chatId, timeStamp);
        bot.sendMessage(ricecab_id, "Let me find out...");

        var photo_file_dir = (path + 'cam.jpg');
        exec('raspistill -vf -hf -o ' + photo_file_dir, function(err, io_data) {
            if (err) {
                bot.sendMessage(ricecab_id, "ERROR: '/what_is_evan_doing' Unable to generate photo.");
            } else {
                send_photo(ricecab_id, photo_file_dir, timeStamp.toString());
            }
        });
    }
});

///////////////////////////////////////////////////////////////////// AUTOMATION

cron.schedule('* 0 0 1 1-12 *', function() {
    console.log("[RESET request by AUTOMATION: APPROVED]");
    reset_all();
    setTimeout(console.log("[RESET request completed.]"), 1000*60*5); // 5min timeout.
});

function reset_all() {
    var timeStamp = new Date();
    var line = "\n💰*💰*💰*💰*💰*💰*💰*💰*💰\n\n";

    var l0 = "💰💰 PAYDAY INFORMATION 💰💰\n\n"
    + "Hey all! I have just been informed by my master, @evanlinjin, "
    + "that it is time for you all to pay your share of money.\n\n"
    + "Please transfer the required amount of money (shown below) "
    + "to his bank account: " + bank_acc + ".\n";

    exec('cat ' + path + 'stats/*', function(err, file_data) {
        if (err) {
            bot.sendMessage(ricecab_id, l0 + line + "Nothing to show.\n" + line + timeStamp);
        } else {
            bot.sendMessage(ricecab_id, l0 + line + file_data.toString() + line + timeStamp);

            // RESET ALL >>
            exec('rm ' + path + 'stats/* ' + path + 'logs/*', function(err, rm_output) {
                if (err) {
                    bot.sendMessage(ricecab_id, "ERROR: '/reset' request error.");
                    console.log(ricecab_id + " ERROR: '/reset' request error.");
                }
            });
        }
    });
}

/////////////////////////////////////////////////////////////// CAMERA FUNCTIONS

function send_photo(chat_id, photo_file_dir, caption_desc) {
    bot.sendPhoto(chat_id, photo_file_dir, {caption: caption_desc});
}

///////////////////////////////////////////////////// Speech Recognition Arrays.

var SRA_ride = ['give~aride', 'getaride', 'driveme', 'pick~up', 'need~ride'];

var SRA_morning = ['morning', 'touni'];
var SRA_evening = ['evening', 'afternoon', 'wayback', 'fromuni', 'backhome', 'ridehome'];

///////////////////////////////////////////////////////////////////////// Logic.

bot.on('message', function (msg) {
    var chatId = msg.chat.id;
    var user1stName = msg.from.first_name;
    var str = msg.text; str = str.replace(/\s+/g, '').toLowerCase();

    switch (str) {
        case 'whereisevan?':
            bot.sendMessage(chatId, "Good question.");
            break;

        default:
        if (str.search('thanks') !== -1) {
            bot.sendMessage(chatId, "You're Welcome 😘");
        }
        if (if_include(str, SRA_ride) && if_include(str, 'tomorrow')) {

            var rdmsg = [
                "It is understood that ",
                " needs a ride tomorrow ",
                ". Evan will be informed! 🗣👌📢👍📡😊"
            ];

            if (if_include(str, SRA_morning)) {
                bot.sendMessage(chatId, rdmsg[0] + user1stName + rdmsg[1] + SRA_morning[0] + rdmsg[2]);
                inform_admin(user1stName + ' needs a ride tomorrow morning.');
            }
            if (if_include(str, SRA_evening)) {
                bot.sendMessage(chatId, rdmsg[0] + user1stName + rdmsg[1] + SRA_evening[0] + rdmsg[2]);
                inform_admin(user1stName + ' needs a ride tomorrow evening.');
            }
        }
    }
});

////////////////////////////////////////////////// Speech Recognition Functions.

// Should really only check a scentence at a time for accuracy.
function if_include(in_msg, phrases) {

    for (var i = 0; i < phrases.length; i++) {
        if (in_msg.search(phrases[i]) !== -1) {return true;}
        console.log('comparing: ' + in_msg + ' with: ' + phrases[i] + '.');

        // CHECK >> '~' :
        if (phrases[i].search('~') !== -1) {
            var temp_phrases = phrases[i].split('~');
            var n_incld = 0;

            for (var j = 0; j < temp_phrases.length; j++) {
                if (in_msg.search(temp_phrases[j]) !== -1) {n_incld = n_incld + 1;}
            }
            if (n_incld === temp_phrases.length) {return true;}
        }
    }
    return false;
}

//////////////////////////////////////////////// '/checkin' & '/stats' functions

// Get number of rides from specified user.
function get_n_rides(path, user_id) {
    fs.readFile(path + 'logs/' + user_id + '.txt', function(err, data) {
        if (err) {
            var err_msg = "ERROR: Unable to get number of 'checkin's from " + user_id + ". Assuming 0.";
            bot.sendMessage(-116496721, err_msg); console.log(-116496721 + err_msg);
            return 0;
        }

        var file_str = data.toString();
        var n_checkin = 0;

        for (var i = 0; i < file_str.length; i++) {
            if (file_str[i] === '[') { n_checkin += 1; }
        }
        bot.sendMessage(user_id, "within get_n_rides: " + n_checkin);
        return n_checkin;
    });
}

// Get total cost from specified user.
function get_total_cost(path, user_id) {
    fs.readFile(path + 'logs/' + user_id + '.txt', function(err, data) {
        if (err) {
            var err_msg = "ERROR: Unable to get number of 'checkin's from " + user_id + ". Assuming 0.";
            bot.sendMessage(-116496721, err_msg); console.log(-116496721 + err_msg);
        }

        // Convert data to lowercase, spaceless string.
        var file_str = data.toString();
        file_str = file_str.replace(/\s+/g, '').toLowerCase();

        var cmp_str = 'COST';
        var total_cost = 0.00;

        for (var i = 0; i < file_str.length; i++) {

            // Find 'COST' in string.
            if (
                file_str[i] === cmp_str[0] &&
                file_str.slice(i, i + cmp_str.length) === cmp_str
            ) {
                // Move to after 'COST' term.
                i += cmp_str.length;

                // Find positions of two preceeding '"'s.
                var pos_PA = [];
                while (true) {
                    if (file_str[i] === '"') { pos_PA.push(i); }
                    if (pos_PA.length === 2) { break; }
                    i += 1;
                }

                // Extract 'COST' value and add to 'total_cost'.
                total_cost += parseFloat(file_str.slice(pos_PA[0] + 1, pos_PA[1]));
            }
        }
        return total_cost;
    });
    return 0.00;
}

////////////////////////////////////////////////////////// CONSOLE LOG FUNCTIONS

function access_denied(cmd, userName, userId, chatId, timeStamp) {
    var msg = "ON " + timeStamp + " >>\n" +
    "[ACCESS DENIED] CMD: '" + cmd + "'" +
    ", Name: "    + userName +
    ", User ID: " + userId +
    ", Chat ID: " + chatId + "\n";
    console.log(msg);
}

function access_granted(cmd, userName, userId, chatId, timeStamp) {
    var msg = "ON " + timeStamp + " >>\n" +
    "[ACCESS GRANTED] CMD: '" + cmd + "'" +
    ", Name: "    + userName +
    ", User ID: " + userId +
    ", Chat ID: " + chatId + "\n";
    console.log(msg);
}

function inform_admin(admin_msg) {bot.sendMessage(133607928, admin_msg);}
<commit_msg>Begin removing dependance on wc.<commit_after>///////////////////////////////////////////////////////////////// Library Setup:

var TelegramBot = require('node-telegram-bot-api');
var fs = require('fs');
var exec = require('child_process').exec;
var cron = require('node-cron');

//////////////////////////////////////////////// Load "Ricecab Bot" Information:

var token = '216808904:AAFqAjnnVVpHmKU4ZsExIMNuUdZX8R49YSQ';
var bot = new TelegramBot(token, {polling: true});
var ricecab_id = -116496721;
var bank_acc = '12-3086-0261060-00';
var path = '/home/pi/ricecab_bot/';

/////////////////////////////////////////////////////// Load "User Information":

var users = [
    {id : 133607928, cost: 2.52}, // Evan Lin
    {id : 177677828, cost: 0.48}, // Honour Carmichael
    {id : 177893563, cost: 1.52}, // Carl Velasco
    {id : 187936081, cost: 2.52}, // Amy Lai
    {id : 199377811, cost: 1.21}, // Vincent Wolfgramm-Russel
    {id : 197336637, cost: 2.52}  // Jay Shen
];

function uget_index(id) {
    for (var i = 0; i < users.length; i++) {
        if (users[i].id === id) {return i;}
    }
    return 0;
}

//////////////////////////////////////////////// "Ricecab Bot" Logic Definition:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/checkin"

bot.onText(/\/checkin/, function(msg, match) {
    var chatId = msg.chat.id;
    var userName = msg.from.first_name + ' ' + msg.from.last_name;
    var userId = msg.from.id;
    var timeStamp = msg.date;

    // FIND MONTHLY SUM >>
    var tripcost = users[uget_index(userId)].cost;
    var cost_sum = get_total_cost(path, userId) + tripcost; // costsum after checkin.
    var n_rides = get_n_rides(path, userId); // Number of rides after checkin.
    bot.sendMessage(userId, n_rides);

    // DATA STRING >>
    var data = '['
    + 'CHECKIN:"' + timeStamp + '"'
    + ', NAME:"' + userName + '"'
    + ', ID:"' + userId + '"'
    + ', COST:"' + tripcost + '"'
    + ', MONTHLY_SUM:"' + cost_sum + '"'
    + ']\n';

    // FILE IO >>
    // Make Stats File.
    var l1 = "NAME: " + userName + ", ";
    var l2 = "RIDES: " + n_rides + ", ";
    var l3 = "SUM: $" + cost_sum + "\n";

    fs.writeFile(path + 'stats/' + userId + '.txt', l1 + l2 + l3, function(err) {
        if(err) {
            bot.sendMessage(chatId, "ERROR: '/checkin' stats cannot be compiled.");
            console.log(chatId + " ERROR: '/checkin' stats cannot be compiled.");
        }
    });

    // Append to Log File.
    fs.appendFile(path + 'logs/' + userId + '.txt', data, function(err) {
        if(err) {
            bot.sendMessage(chatId, "ERROR: '/checkin' request error.");
            console.log(chatId + " ERROR: '/checkin' request error.");
        }

        // PREPARE PERSONAL MESSAGE >>
        var checkin_msg = "CHECKIN SUCCESSFUL at '" + timeStamp + "'.\n"
            + "Name: " + userName + ", Cost: $" + tripcost + "\n"
            + "Run /stats for more details.";
        bot.sendMessage(chatId, checkin_msg);

        // PREPARE GLOBAL MESSAGE >>
        bot.sendMessage(ricecab_id, userName + " has checked in.");
    });
    console.log(data); // CONSOLE LOG.

});

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/info"
bot.onText(/\/info/, function(msg, match) {
    var chatId = msg.chat.id;

    fs.readFile(path + 'INFO', function(err, data) {
        if (err) {
            bot.sendMessage(chatId, "ERROR: '/info' request has issues.");
            console.log(chatId + " ERROR: '/info' request has issues.");
        }
        bot.sendMessage(chatId, data.toString());
        console.log("[INFO request on " + chatId + "]");
    });
});

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/stats"
bot.onText(/\/stats/, function(msg, match) {

    var chatId = msg.chat.id;
    var userName = msg.from.first_name + ' ' + msg.from.last_name;
    var userId = msg.from.id;

    // Attempt to refresh stats.
    for (var i = 0; i < users.length; i++) {

    }

    // Output Stats >>

    var l0 = "** STATS **\n";

    exec('cat ' + path + 'stats/*', function(err, file_data) {
        if (err) {
            bot.sendMessage(chatId, l0 + "Nothing to show.");
        } else {
            bot.sendMessage(chatId, l0 + file_data.toString());
        }
        console.log("[STATS request on " + chatId + "]");
    });
});

///////////////////////////////////////////////////////// ADMINISTRATOR COMMANDS

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/\"
bot.onText(/\/go/, function(msg, match) {
    var userName = msg.from.first_name + ' ' + msg.from.last_name;
    if (msg.from.id === 133607928) {
        bot.sendMessage(ricecab_id, "Evan is on his way to the car now!");
        console.log("[GO request by " + userName + ": APPROVED]");
    } else {
        console.log("[GO request by " + userName + ": REJECTED]");
    }
});

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/reset"
bot.onText(/\/reset/, function(msg, match) {
    var userName = msg.from.first_name + ' ' + msg.from.last_name;
    if (msg.from.id === 133607928) {
        reset_all();
        console.log("[RESET request by " + userName + ": APPROVED]");
    } else {
        console.log("[RESET request by " + userName + ": REJECTED]");
    }
});

//////////////////////////////////////////////////////////////////////////// FUN

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "/photo"
bot.onText(/\/what_is_evan_doing/, function(msg, match) {
    var chatId = msg.chat.id;
    var userName = msg.from.first_name + ' ' + msg.from.last_name;
    var userId = msg.from.id;
    var timeStamp = new Date();

    if (msg.chat.id !== ricecab_id) {
        access_denied( '/photo', userName, userId, chatId, timeStamp);
    } else {
        access_granted( '/photo', userName, userId, chatId, timeStamp);
        bot.sendMessage(ricecab_id, "Let me find out...");

        var photo_file_dir = (path + 'cam.jpg');
        exec('raspistill -vf -hf -o ' + photo_file_dir, function(err, io_data) {
            if (err) {
                bot.sendMessage(ricecab_id, "ERROR: '/what_is_evan_doing' Unable to generate photo.");
            } else {
                send_photo(ricecab_id, photo_file_dir, timeStamp.toString());
            }
        });
    }
});

///////////////////////////////////////////////////////////////////// AUTOMATION

cron.schedule('* 0 0 1 1-12 *', function() {
    console.log("[RESET request by AUTOMATION: APPROVED]");
    reset_all();
    setTimeout(console.log("[RESET request completed.]"), 1000*60*5); // 5min timeout.
});

function reset_all() {
    var timeStamp = new Date();
    var line = "\n💰*💰*💰*💰*💰*💰*💰*💰*💰\n\n";

    var l0 = "💰💰 PAYDAY INFORMATION 💰💰\n\n"
    + "Hey all! I have just been informed by my master, @evanlinjin, "
    + "that it is time for you all to pay your share of money.\n\n"
    + "Please transfer the required amount of money (shown below) "
    + "to his bank account: " + bank_acc + ".\n";

    exec('cat ' + path + 'stats/*', function(err, file_data) {
        if (err) {
            bot.sendMessage(ricecab_id, l0 + line + "Nothing to show.\n" + line + timeStamp);
        } else {
            bot.sendMessage(ricecab_id, l0 + line + file_data.toString() + line + timeStamp);

            // RESET ALL >>
            exec('rm ' + path + 'stats/* ' + path + 'logs/*', function(err, rm_output) {
                if (err) {
                    bot.sendMessage(ricecab_id, "ERROR: '/reset' request error.");
                    console.log(ricecab_id + " ERROR: '/reset' request error.");
                }
            });
        }
    });
}

/////////////////////////////////////////////////////////////// CAMERA FUNCTIONS

function send_photo(chat_id, photo_file_dir, caption_desc) {
    bot.sendPhoto(chat_id, photo_file_dir, {caption: caption_desc});
}

///////////////////////////////////////////////////// Speech Recognition Arrays.

var SRA_ride = ['give~aride', 'getaride', 'driveme', 'pick~up', 'need~ride'];

var SRA_morning = ['morning', 'touni'];
var SRA_evening = ['evening', 'afternoon', 'wayback', 'fromuni', 'backhome', 'ridehome'];

///////////////////////////////////////////////////////////////////////// Logic.

bot.on('message', function (msg) {
    var chatId = msg.chat.id;
    var user1stName = msg.from.first_name;
    var str = msg.text; str = str.replace(/\s+/g, '').toLowerCase();

    switch (str) {
        case 'whereisevan?':
            bot.sendMessage(chatId, "Good question.");
            break;

        default:
        if (str.search('thanks') !== -1) {
            bot.sendMessage(chatId, "You're Welcome 😘");
        }
        if (if_include(str, SRA_ride) && if_include(str, 'tomorrow')) {

            var rdmsg = [
                "It is understood that ",
                " needs a ride tomorrow ",
                ". Evan will be informed! 🗣👌📢👍📡😊"
            ];

            if (if_include(str, SRA_morning)) {
                bot.sendMessage(chatId, rdmsg[0] + user1stName + rdmsg[1] + SRA_morning[0] + rdmsg[2]);
                inform_admin(user1stName + ' needs a ride tomorrow morning.');
            }
            if (if_include(str, SRA_evening)) {
                bot.sendMessage(chatId, rdmsg[0] + user1stName + rdmsg[1] + SRA_evening[0] + rdmsg[2]);
                inform_admin(user1stName + ' needs a ride tomorrow evening.');
            }
        }
    }
});

////////////////////////////////////////////////// Speech Recognition Functions.

// Should really only check a scentence at a time for accuracy.
function if_include(in_msg, phrases) {

    for (var i = 0; i < phrases.length; i++) {
        if (in_msg.search(phrases[i]) !== -1) {return true;}
        console.log('comparing: ' + in_msg + ' with: ' + phrases[i] + '.');

        // CHECK >> '~' :
        if (phrases[i].search('~') !== -1) {
            var temp_phrases = phrases[i].split('~');
            var n_incld = 0;

            for (var j = 0; j < temp_phrases.length; j++) {
                if (in_msg.search(temp_phrases[j]) !== -1) {n_incld = n_incld + 1;}
            }
            if (n_incld === temp_phrases.length) {return true;}
        }
    }
    return false;
}

//////////////////////////////////////////////// '/checkin' & '/stats' functions

// Get number of rides from specified user.
function get_n_rides(path, user_id) {
    fs.readFile(path + 'logs/' + user_id + '.txt', function(err, data) {
        if (err) {
            var err_msg = "ERROR: Unable to get number of 'checkin's from " + user_id + ". Assuming 0.";
            bot.sendMessage(-116496721, err_msg); console.log(-116496721 + err_msg);
            return 0;
        }

        var file_str = data.toString();
        var n_checkin = 0;

        for (var i = 0; i < file_str.length; i++) {
            if (file_str[i] === '[') { n_checkin += 1; }
        }
        bot.sendMessage(user_id, "within get_n_rides: " + n_checkin);
        return n_checkin;
    });
}

// Get total cost from specified user.
function get_total_cost(path, user_id) {
    fs.readFile(path + 'logs/' + user_id + '.txt', function(err, data) {
        if (err) {
            var err_msg = "ERROR: Unable to get number of 'checkin's from " + user_id + ". Assuming 0.";
            bot.sendMessage(-116496721, err_msg); console.log(-116496721 + err_msg);
        }

        // Convert data to lowercase, spaceless string.
        var file_str = data.toString();
        file_str = file_str.replace(/\s+/g, '').toLowerCase();

        var cmp_str = 'COST';
        var total_cost = 0.00;

        for (var i = 0; i < file_str.length; i++) {

            // Find 'COST' in string.
            if (
                file_str[i] === cmp_str[0] &&
                file_str.slice(i, i + cmp_str.length) === cmp_str
            ) {
                // Move to after 'COST' term.
                i += cmp_str.length;

                // Find positions of two preceeding '"'s.
                var pos_PA = [];
                while (true) {
                    if (file_str[i] === '"') { pos_PA.push(i); }
                    if (pos_PA.length === 2) { break; }
                    i += 1;
                }

                // Extract 'COST' value and add to 'total_cost'.
                total_cost += parseFloat(file_str.slice(pos_PA[0] + 1, pos_PA[1]));
            }
        }
        return total_cost;
    });
    return 0.00;
}

////////////////////////////////////////////////////////// CONSOLE LOG FUNCTIONS

function access_denied(cmd, userName, userId, chatId, timeStamp) {
    var msg = "ON " + timeStamp + " >>\n" +
    "[ACCESS DENIED] CMD: '" + cmd + "'" +
    ", Name: "    + userName +
    ", User ID: " + userId +
    ", Chat ID: " + chatId + "\n";
    console.log(msg);
}

function access_granted(cmd, userName, userId, chatId, timeStamp) {
    var msg = "ON " + timeStamp + " >>\n" +
    "[ACCESS GRANTED] CMD: '" + cmd + "'" +
    ", Name: "    + userName +
    ", User ID: " + userId +
    ", Chat ID: " + chatId + "\n";
    console.log(msg);
}

function inform_admin(admin_msg) {bot.sendMessage(133607928, admin_msg);}
<|endoftext|>


<commit_before>/* global SolidAuthClient, SolidUtils, $rdf */

TweeFiUtils = {

    TweetUri: class {
        constructor(value) {
            // Regex-pattern to check URLs against:
            // https://twitter.com/<twitteruser>/status/<long number>
            var urlRegex = /^https:\/\/twitter.com\/([a-zA-Z _.,!"'/$]+)\/status\/([0-9]*$)/;
            this.match = urlRegex.exec(value);
            this.value = value;
        }

        isValid() {
            return this.match !== null;
        }

        getUser() {
            return this.match[1];
        }

        getStatus() {
            return this.match[2];
        }

        toString() {
            return this.value;
        }
    },
    updateLoginInfo() {
        SolidAuthClient.currentSession().then(function (session) {
            var user = $rdf.sym(session.webId);
            SolidUtils.rdfFetch(session.webId).then(function (response) {
                var name = response.graph.any(user, SolidUtils.vocab.foaf('name'));
                $("#loginInfo").html("Logged in as:");
                $("#loginName").html("" + name + "");
            });
        });
    }

}<commit_msg>Check when session is null<commit_after>/* global SolidAuthClient, SolidUtils, $rdf */

TweeFiUtils = {

    TweetUri: class {
        constructor(value) {
            // Regex-pattern to check URLs against:
            // https://twitter.com/<twitteruser>/status/<long number>
            var urlRegex = /^https:\/\/twitter.com\/([a-zA-Z _.,!"'/$]+)\/status\/([0-9]*$)/;
            this.match = urlRegex.exec(value);
            this.value = value;
        }

        isValid() {
            return this.match !== null;
        }

        getUser() {
            return this.match[1];
        }

        getStatus() {
            return this.match[2];
        }

        toString() {
            return this.value;
        }
    },
    updateLoginInfo() {
        SolidAuthClient.currentSession().then(function (session) {
            if (session) {
            var user = $rdf.sym(session.webId);
            SolidUtils.rdfFetch(session.webId).then(function (response) {
                var name = response.graph.any(user, SolidUtils.vocab.foaf('name'));
                $("#loginInfo").html("Logged in as:");
                $("#loginName").html("" + name + "");
            });
        } else {
            $("#loginInfo").html("Not logged in");
        }
        });
    }

}<|endoftext|>


<commit_before>
let zip = [];
let completezip = [];
let errorzip = [];
let all_url_stack = "";//lock
let datalockcount = 0;
const subDomainList = ["la","aa","ba"];
const callPerServer = 2;
const download_array = [];

let a = "";
a.on
download_array[0] = function download_html(zipnumber , passlockcount) {
    download_hitomi_html(zipnumber , passlockcount);
}

download_array[1] = function download_hitomi_js(zipnumber , passlockcount ) {
    $.ajax({
        url: 'http://localhost:443/https://hitomi.la/galleries/'+ zip[zipnumber].filenumber +'.js',
        //async:false,
        success: function() {
            $.each(galleryinfo, function(i, image) {
                zip[zipnumber].pushimageurl(url_from_url(zip[zipnumber].filenumber + "/" +image.name , i));
                zip[zipnumber].pushimagename(image.name);
            });
            returnlock(passlockcount).then(isworking() , thenerror());

        },
        error: function() {
            zip[zipnumber].imageurl = ["error"];
            zip[zipnumber].imagename = ["error"];
            returnlock(passlockcount).then(isworking() , thenerror());
        }
    });
}

class zipmember{
    constructor()
    {
        this.filename = "";//for save file
        this.fileurl = "";//for save original url
        this.filenumber = "";//for download
        this.imagename = [];//for save imagefile
        this.imageurl = [];//for download
        this.jszip = new JSZip();
        this.threadcount = 0;
    }

    get filename() {return this._filename; }
    get fileurl() {return this._fileurl; }
    get filenumber() {return this._filenumber; }
    get imagename() {return this._imagename; }
    get imageurl() {return this._imageurl; }
    get jszip() {return this._jszip; }
    get threadcount() {return this._threadcount; }

    set filename(stri) {this._filename = stri; }
    set fileurl(stri) {this._fileurl = stri; this.setfilenumber(stri);}
    set filenumber(stri) { }
    set imagename(arra) { if(Array.isArray(arra)){this._imagename = arra;} }
    set imageurl(arra) {if(Array.isArray(arra)){this._imageurl = arra;} }
    set jszip(jszi) {this._jszip = jszi;}//need block if not JSzip
    set threadcount(inte) {this._threadcount = inte; }

    pushimagename(stri){
        this.imagename.push(stri);
    };
    pushimageurl(stri){
        this.imageurl.push(stri);
    };
    unlockthread(){
        this.threadcount = this.threadcount -1;
    };
    setfilenumber(inputurl){
        let urltext = inputurl.split("/");
        let linkid = "";
        if(urltext[0] == "e-hentai.org" || urltext[0] == "exhentai.org") {
            if(urltext[1] == "g") {
                linkid = urltext[urltext.length-3];
            }
            else if(urltext == "s") {
                linkid = urltext[urltext.length-1].split("-")[0];
            }
        }
        else if(urltext[0] == "hitomi.la"){
            linkid = urltext[urltext.length-1].split(".")[0];
        }
        else{
            linkid = "error";
        }
        this._filenumber = linkid;
    }
}

function  initzipnumber(zipnumber) {
    zip[zipnumber] = new zipmember();
}

$(document).ready(function() {
    $('#getData').click(function () {
        if (datalockcount == 0 && zip.length == 0) {
            //need disable button
            printwithTime("start------------");
            download_get(all_url_stack + $('#input_url').val(), $('#input_fileName').val());
            all_url_stack = "";
        }
        else {
            all_url_stack = all_url_stack + $('#input_url').val() , $('#input_fileName').val();
            printwithTime("ready for add download url-----------");
        }
    });
});

function download_get(galleryhtml) {
        let inputurl = galleryhtml.split("https://");
        inputurl.shift();
        getfiledata(inputurl);
}

function getfiledata(inputurl){
    let linkid = 0;
    let pushnumber = zip.length;
    let inputurllength = inputurl.length;
    let passlockcount = datalockcount;
    let download_arraylength = download_array.length;

    setthreadlock(inputurllength * download_arraylength);

    for(let zipnumber = 0; zipnumber < inputurllength ; zipnumber++) {
        initzipnumber(zipnumber+ pushnumber);

        zip[zipnumber+ pushnumber].fileurl = inputurl[zipnumber];

        for(let i = 0 ; i < download_arraylength ; i++)
        {
            download_array[i](zipnumber+ pushnumber , passlockcount);
        }
    }
}

function setthreadlock(number) {
    datalockcount = datalockcount + number;
    return new Promise(function (resolve, reject) {
        if (datalockcount >= 0) {
            resolve();
        }
        else {
            reject();
        }
    });
};

function returnlock(passlockcount) {
    datalockcount = datalockcount -1;
    return new Promise(function (resolve, reject) {
        if (  !  (datalockcount < passlockcount)) {
            resolve();
        }
        else {
            reject();
        }
    });
}

function download_html(zipnumber , passlockcount) {
    download_hitomi_html(zipnumber , passlockcount);
}

function download_hitomi_html(zipnumber , passlockcount)
{
        $.ajax({
            url: 'http://localhost:443/https://hitomi.la/galleries/' + zip[zipnumber].filenumber + '.html',
            //async:false,
            success: function (data) {
                let text1 = textsplit(data , "-gallery" , "gallery-info");

                let datatext = textsplit(text1 , "h1>" , "</h1");
                datatext = textsplit(datatext , ".html\">" , "</a");

                let creatertext = textsplit(text1 , "h2>" , "</h2");
                creatertext = textsplit(creatertext , ".html\">" , "</a");

                if(datatext == ""){
                    datatext = zip[zipnumber].filenumber ;
                }

                if(creatertext == ""){
                    creatertext = "N_A";
                }

                zip[zipnumber].filename = creatertext + "__" + datatext;
                returnlock(passlockcount).then(isworking() , thenerror());
            },
            error: function() {
                zip[zipnumber].filename = zip[zipnumber].filenumber;
                returnlock(passlockcount).then(isworking() , thenerror());
            }
        });
}

function textsplit(data , sp1 , sp2)
{
    if(data.indexOf(sp1) != -1 && data.indexOf(sp2) != -1){
        let text = data.split(sp1)[1].split(sp2)[0];
        return text;
    }
    else{
        return "";
    }
}

function download_hitomi_js(zipnumber , passlockcount ) {
    $.ajax({
        url: 'http://localhost:443/https://hitomi.la/galleries/'+ zip[zipnumber][1] +'.js',
        //async:false,
        success: function() {
            $.each(galleryinfo, function(i, image) {
                zip[zipnumber].pushimageurl(url_from_url(zip[zipnumber].filenumber + "/" +image.name , i));
                zip[zipnumber].pushimagename(image.name);
            });
            zip[zipnumber].threadcount = zip[zipnumber].imageurl.length;
            returnlock(passlockcount).then(isworking() , thenerror());

        },
        error: function() {
            //zip[zipnumber].pushimageurl(url_from_url(zip[zipnumber].filenumber + "/" +image.name , i));
            //zip[zipnumber].pushimagename(image.name);
            zip[zipnumber].threadcount = 0;
            returnlock(passlockcount).then(isworking() , thenerror());
        }
    });
}

function url_from_url(url , i) {
    return "http://localhost:443/https://" + subdomain_from_url(i) + ".hitomi.la/galleries/"+ url;
}

function subdomain_from_url(i) {
    let retval = subDomainList[i%subDomainList.length];
    return retval;
}

function isworking()
{
    if(all_url_stack != "")
    {
        download_get(all_url_stack);
        all_url_stack = "";
    }
    else if(datalockcount == 0 && (zip.length > 0))
    {
        if(zip[0].imageurl[0] == "error")
        {
            errorzip.push(zip.shift());
            isworking();
        }
        else
        {
            getimagedata(0);
        }
    }
    else if(datalockcount == 0 && zip.length == 0 )
    {
        printwithTime("finish------");
    }
    else if(datalockcount > 0 && zip.length > 0)
    {

    }
    else
    {
        printwithTime("error in isworking - " + zip[0].fileurl + "\ndatalockcount = " + datalockcount + "\nzip.length = " + zip.length);
    }
}

function getimagedata(zipnumber) {
    for(let i = 0 ; (i < subDomainList.length * callPerServer) && (i < zip[zipnumber].imageurl.length) ; i ++){
        download_next_image(i , zipnumber);
    }
}

function download_next_image(index , zipnumber) {
    ajax_download_blob(index, zipnumber , 0);
}

function ajax_download_blob(index, zipnumber , count) {
    let xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function() {
        if(this.readyState == 4) {
            if( this.status == 200 || this.status == 304) {
                image_downloaded(this.response , index, zipnumber);
            }

            else {
                if(count < 10) {
                    ajax_download_blob(index, zipnumber, count + 1);
                }
                else {
                    alert("error on picture number" + index +"-- error " + this.status);
                    //need whar file
                }
            }
        }
    }
    xhr.open('GET', zip[zipnumber].imageurl[index]);
    xhr.responseType = 'arraybuffer';
    xhr.send();
}

function image_downloaded(imgData , index, zipnumber) {
    zip[zipnumber].jszip.file(zip[zipnumber].imagename[index], imgData, {base64: true});
    zip[zipnumber].unlockthread();
        // > maybe wrong
    if (zip[zipnumber].threadcount <= 0) {// need check error when threadcount < 0 ;
        let content = zip[zipnumber].jszip.generateAsync({type:"blob"})
        .then(function (blob) {
            saveAs(blob, zip[zipnumber].filename+".zip")
                .then(nextcontent(blob , zipnumber) , thenerror());
        }  , thenerror());
    }
    else if (index + subDomainList.length * callPerServer < zip[zipnumber].imageurl.length){//maybe i can upgrade
        download_next_image(index + subDomainList.length * callPerServer , zipnumber);
    }
    else
    {
        //empty
    }
}

function thenerror(){}

function nextcontent(blob , zipnumber){
    var completeziplength = completezip.length
    completezip.push(zip.shift());
    completezip[completeziplength].jszip = "";
    completezip[completeziplength].imageurl = [""];
    completezip[completeziplength].imagename = [""];
    printwithTime(completezip[completeziplength].filename+".zip finish");
    //blob.close();
    isworking(0)
}

function printwithTime(str) {
    $('#finished_list').val( new Date().toLocaleTimeString() + ":\n " + str + "\n\n" + $('#finished_list').val());
}

<commit_msg>fix thread lock<commit_after>
let zip = [];
let completezip = [];
let errorzip = [];
let all_url_stack = "";//lock
let datalockcount = 0;
const subDomainList = ["la","aa","ba"];
const callPerServer = 2;
const download_array = [];

let a = "";
a.on
download_array[0] = function download_html(zipnumber , passlockcount) {
    download_hitomi_html(zipnumber , passlockcount);
}

download_array[1] = function download_hitomi_js(zipnumber , passlockcount ) {
    $.ajax({
        url: 'http://localhost:443/https://hitomi.la/galleries/'+ zip[zipnumber].filenumber +'.js',
        //async:false,
        success: function() {
            $.each(galleryinfo, function(i, image) {
                zip[zipnumber].pushimageurl(url_from_url(zip[zipnumber].filenumber + "/" +image.name , i));
                zip[zipnumber].pushimagename(image.name);
            });
            returnlock(passlockcount).then(isworking() , thenerror());

        },
        error: function() {
            zip[zipnumber].imageurl = ["error"];
            zip[zipnumber].imagename = ["error"];
            returnlock(passlockcount).then(isworking() , thenerror());
        }
    });
}

class zipmember{
    constructor()
    {
        this.filename = "";//for save file
        this.fileurl = "";//for save original url
        this.filenumber = "";//for download
        this.imagename = [];//for save imagefile
        this.imageurl = [];//for download
        this.jszip = new JSZip();
        this.threadcount = 0;
    }

    get filename() {return this._filename; }
    get fileurl() {return this._fileurl; }
    get filenumber() {return this._filenumber; }
    get imagename() {return this._imagename; }
    get imageurl() {return this._imageurl; }
    get jszip() {return this._jszip; }
    get threadcount() {return this._threadcount; }

    set filename(stri) {this._filename = stri; }
    set fileurl(stri) {this._fileurl = stri; this.setfilenumber(stri);}
    set filenumber(stri) { }
    set imagename(arra) { if(Array.isArray(arra)){this._imagename = arra;} }
    set imageurl(arra) {if(Array.isArray(arra)){this._imageurl = arra;}}
    set jszip(jszi) {this._jszip = jszi;}//need block if not JSzip
    set threadcount(inte) {this._threadcount = inte; }

    pushimagename(stri){
        this._imagename.push(stri);
    };
    pushimageurl(stri){
        this._imageurl.push(stri);
    };
    unlockthread(){
        this._threadcount = this._threadcount -1;
    };
    setfilenumber(inputurl){
        let urltext = inputurl.split("/");
        let linkid = "";
        if(urltext[0] == "e-hentai.org" || urltext[0] == "exhentai.org") {
            if(urltext[1] == "g") {
                linkid = urltext[urltext.length-3];
            }
            else if(urltext == "s") {
                linkid = urltext[urltext.length-1].split("-")[0];
            }
        }
        else if(urltext[0] == "hitomi.la"){
            linkid = urltext[urltext.length-1].split(".")[0];
        }
        else{
            linkid = "error";
        }
        this._filenumber = linkid;
    }
}

function  initzipnumber(zipnumber) {
    zip[zipnumber] = new zipmember();
}

$(document).ready(function() {
    $('#getData').click(function () {
        if (datalockcount == 0 && zip.length == 0) {
            //need disable button
            printwithTime("start------------");
            download_get(all_url_stack + $('#input_url').val(), $('#input_fileName').val());
            all_url_stack = "";
        }
        else {
            all_url_stack = all_url_stack + $('#input_url').val() , $('#input_fileName').val();
            printwithTime("ready for add download url-----------");
        }
    });
});

function download_get(galleryhtml) {
        let inputurl = galleryhtml.split("https://");
        inputurl.shift();
        getfiledata(inputurl);
}

function getfiledata(inputurl){
    let linkid = 0;
    let pushnumber = zip.length;
    let inputurllength = inputurl.length;
    let passlockcount = datalockcount;
    let download_arraylength = download_array.length;

    setthreadlock(inputurllength * download_arraylength);

    for(let zipnumber = 0; zipnumber < inputurllength ; zipnumber++) {
        initzipnumber(zipnumber+ pushnumber);

        zip[zipnumber+ pushnumber].fileurl = inputurl[zipnumber];

        for(let i = 0 ; i < download_arraylength ; i++)
        {
            download_array[i](zipnumber+ pushnumber , passlockcount);
        }
    }
}

function setthreadlock(number) {
    datalockcount = datalockcount + number;
    return new Promise(function (resolve, reject) {
        if (datalockcount >= 0) {
            resolve();
        }
        else {
            reject();
        }
    });
};

function returnlock(passlockcount) {
    datalockcount = datalockcount -1;
    return new Promise(function (resolve, reject) {
        if (  !  (datalockcount < passlockcount)) {
            resolve();
        }
        else {
            reject();
        }
    });
}

function download_html(zipnumber , passlockcount) {
    download_hitomi_html(zipnumber , passlockcount);
}

function download_hitomi_html(zipnumber , passlockcount)
{
        $.ajax({
            url: 'http://localhost:443/https://hitomi.la/galleries/' + zip[zipnumber].filenumber + '.html',
            //async:false,
            success: function (data) {
                let text1 = textsplit(data , "-gallery" , "gallery-info");

                let datatext = textsplit(text1 , "h1>" , "</h1");
                datatext = textsplit(datatext , ".html\">" , "</a");

                let creatertext = textsplit(text1 , "h2>" , "</h2");
                creatertext = textsplit(creatertext , ".html\">" , "</a");

                if(datatext == ""){
                    datatext = zip[zipnumber].filenumber ;
                }

                if(creatertext == ""){
                    creatertext = "N_A";
                }

                zip[zipnumber].filename = creatertext + "__" + datatext;
                returnlock(passlockcount).then(isworking() , thenerror());
            },
            error: function() {
                zip[zipnumber].filename = zip[zipnumber].filenumber;
                returnlock(passlockcount).then(isworking() , thenerror());
            }
        });
}

function textsplit(data , sp1 , sp2)
{
    if(data.indexOf(sp1) != -1 && data.indexOf(sp2) != -1){
        let text = data.split(sp1)[1].split(sp2)[0];
        return text;
    }
    else{
        return "";
    }
}

function download_hitomi_js(zipnumber , passlockcount ) {
    $.ajax({
        url: 'http://localhost:443/https://hitomi.la/galleries/'+ zip[zipnumber][1] +'.js',
        //async:false,
        success: function() {
            $.each(galleryinfo, function(i, image) {
                zip[zipnumber].pushimageurl(url_from_url(zip[zipnumber].filenumber + "/" +image.name , i));
                zip[zipnumber].pushimagename(image.name);
                //zip[zipnumber].lockthread(); i try set thread lock here. but fail. why?
            });
            returnlock(passlockcount).then(isworking() , thenerror());

        },
        error: function() {
            //zip[zipnumber].pushimageurl(url_from_url(zip[zipnumber].filenumber + "/" +image.name , i));
            //zip[zipnumber].pushimagename(image.name);
            zip[zipnumber].threadcount = 0;//is this really work?
            returnlock(passlockcount).then(isworking() , thenerror());
        }
    });
}

function url_from_url(url , i) {
    return "http://localhost:443/https://" + subdomain_from_url(i) + ".hitomi.la/galleries/"+ url;
}

function subdomain_from_url(i) {
    let retval = subDomainList[i%subDomainList.length];
    return retval;
}

function isworking()
{
    if(all_url_stack != "")
    {
        download_get(all_url_stack);
        all_url_stack = "";
    }
    else if(datalockcount == 0 && (zip.length > 0))
    {
        if(zip[0].imageurl[0] == "error")
        {
            errorzip.push(zip.shift());
            isworking();
        }
        else
        {
            getimagedata(0);
        }
    }
    else if(datalockcount == 0 && zip.length == 0 )
    {
        printwithTime("finish------");
    }
    else if(datalockcount > 0 && zip.length > 0)
    {

    }
    else
    {
        printwithTime("error in isworking - " + zip[0].fileurl + "\ndatalockcount = " + datalockcount + "\nzip.length = " + zip.length);
    }
}

function getimagedata(zipnumber) {
    let imageurllength = zip[zipnumber].imageurl.length -1;
    zip[zipnumber]._threadcount = imageurllength +1;
    let maxthread = subDomainList.length * callPerServer;
    for(let i = 0 ; (i < subDomainList.length * callPerServer) && (i < imageurllength) ; i ++){
        download_next_image(imageurllength -i, zipnumber , maxthread);
    }
}

function download_next_image(index , zipnumber , maxthread) {
    if(index >= 0)
    {
        ajax_download_blob(index, zipnumber , 0 , maxthread);
    }
}

function ajax_download_blob(index, zipnumber , count , maxthread) {
    let xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function() {
        if(this.readyState == 4) {
            if( this.status == 200 || this.status == 304) {
                image_downloaded(this.response , index, zipnumber , maxthread);
            }

            else {
                if(count < 10) {
                    ajax_download_blob(index, zipnumber, count + 1);
                }
                else {
                    alert("error on picture number" + index +"-- error " + this.status);
                    //need whar file
                }
            }
        }
    }
    xhr.open('GET', zip[zipnumber].imageurl[index]);
    xhr.responseType = 'arraybuffer';
    xhr.send();
}

function image_downloaded(imgData , index, zipnumber , maxthread) {
    zip[zipnumber].jszip.file(zip[zipnumber].imagename[index], imgData, {base64: true});
    zip[zipnumber].unlockthread();
        // > maybe wrong
    if (zip[zipnumber].threadcount == 0) {// need check error when threadcount < 0 ;
        let content = zip[zipnumber].jszip.generateAsync({type:"blob"})
        .then(function (blob) {
            saveAs(blob, zip[zipnumber].filename+".zip")
                .then(nextcontent(blob , zipnumber) , thenerror());
        }  , thenerror());
    }
    else{
        download_next_image(index - maxthread , zipnumber , maxthread);
    }
}

function thenerror(){}

function nextcontent(blob , zipnumber){
    var completeziplength = completezip.length
    completezip.push(zip.shift());
    //completezip[completeziplength].jszip = "";
    //completezip[completeziplength].imageurl = [""];
    //completezip[completeziplength].imagename = [""];
    printwithTime(completezip[completeziplength].filename+".zip finish");
    //blob.close();
    isworking()
}

function printwithTime(str) {
    $('#finished_list').val( new Date().toLocaleTimeString() + ":\n " + str + "\n\n" + $('#finished_list').val());
}

<|endoftext|>


<commit_before>define(["js/html/HtmlElement", "js/core/Content", "underscore"], function (HtmlElement, Content, _) {
        return HtmlElement.inherit({
            defaults: {
                tagName: "div"
            },
            $domAttributes: ['class','id', 'style'],
            render: function () {
                if(this.isRendered()){
                    return this.$el;
                }
                // look if the component has a layout defined
                var layout = this.$templates['layout'];
                // if layout template available...
                if (layout) {
                    var children = layout.createComponents({}, this, this);
                    this._initializeLayoutChildren(children);
                }
                return this.callBase();
            },
            _isDOMNodeAttribute: function(attribute){

                return  this.callBase() && ((this.$el && attribute in this.$el) || /^data-/.test(attribute) || _.indexOf(this.$domAttributes, attribute) !== -1);
            },
            _initializeLayoutChildren: function (children) {
                for (var i = 0; i < children.length; i++) {
                    children[i].$rootScope = this;
                    this.addChild(children[i]);
                }
            },
            _renderChild: function (child) {
                this.callBase();
                if (child instanceof Content) {
                    var ref = child.get('name');
                    if (ref) {
                        var placeHolder = this.getPlaceHolder(ref);
                        if (placeHolder) {
                            placeHolder.set({content: child});
                        }
                    }
                }
            },
            _renderLayoutClass: function (layoutClass, oldLayoutClass) {
                _.each(this.$renderedChildren, function (child) {
                    if (oldLayoutClass) {
                        child.removeClass(oldLayoutClass);
                    }
                    if (layoutClass) {
                        child.addClass(layoutClass)
                    }
                });
            },

            _renderTemplateToPlaceHolder: function (templateName, placeholderName, attributes) {
                this.$renderedPlaceholders = this.$renderedPlaceholders || {};
                var renderedComponent = this.$renderedPlaceholders[placeholderName], placeHolder;
                if (!renderedComponent) {
                    var template = this.getTemplate(templateName);
                    if (template) {
                        // or create special method createComponent
                        renderedComponent = template.createInstance(attributes);
                        placeHolder = this.getPlaceHolder(placeholderName);
                        if (placeHolder) {
                            placeHolder.set({content: renderedComponent});
                            this.$renderedPlaceholders[placeholderName] = renderedComponent;
                        } else {
                            // throw "No placeholder '"+placeholderName+"' found";
                        }

                    }
                } else {
                    placeHolder = this.getPlaceHolder(placeholderName);
                    if(placeHolder){
                        placeHolder.set({content: renderedComponent});
                    }
                    renderedComponent.set(attributes);
                }

            },
            _renderId: function (id) {
                if (id) {
                    this.$el.setAttribute("id", id);
                }else{
                    this.$el.removeAttribute("id");
                }

            }
        });
    }
);<commit_msg>removed DomNode attribute check<commit_after>define(["js/html/HtmlElement", "js/core/Content", "underscore"], function (HtmlElement, Content, _) {
        return HtmlElement.inherit({
            defaults: {
                tagName: "div"
            },
            $domAttributes: ['class','id', 'style'],
            render: function () {
                if(this.isRendered()){
                    return this.$el;
                }
                // look if the component has a layout defined
                var layout = this.$templates['layout'];
                // if layout template available...
                if (layout) {
                    var children = layout.createComponents({}, this, this);
                    this._initializeLayoutChildren(children);
                }
                return this.callBase();
            },
            _isDOMNodeAttribute: function(attribute){

                return  this.callBase() && (/^data-/.test(attribute) || _.indexOf(this.$domAttributes, attribute) !== -1);
            },
            _initializeLayoutChildren: function (children) {
                for (var i = 0; i < children.length; i++) {
                    children[i].$rootScope = this;
                    this.addChild(children[i]);
                }
            },
            _renderChild: function (child) {
                this.callBase();
                if (child instanceof Content) {
                    var ref = child.get('name');
                    if (ref) {
                        var placeHolder = this.getPlaceHolder(ref);
                        if (placeHolder) {
                            placeHolder.set({content: child});
                        }
                    }
                }
            },
            _renderLayoutClass: function (layoutClass, oldLayoutClass) {
                _.each(this.$renderedChildren, function (child) {
                    if (oldLayoutClass) {
                        child.removeClass(oldLayoutClass);
                    }
                    if (layoutClass) {
                        child.addClass(layoutClass)
                    }
                });
            },

            _renderTemplateToPlaceHolder: function (templateName, placeholderName, attributes) {
                this.$renderedPlaceholders = this.$renderedPlaceholders || {};
                var renderedComponent = this.$renderedPlaceholders[placeholderName], placeHolder;
                if (!renderedComponent) {
                    var template = this.getTemplate(templateName);
                    if (template) {
                        // or create special method createComponent
                        renderedComponent = template.createInstance(attributes);
                        placeHolder = this.getPlaceHolder(placeholderName);
                        if (placeHolder) {
                            placeHolder.set({content: renderedComponent});
                            this.$renderedPlaceholders[placeholderName] = renderedComponent;
                        } else {
                            // throw "No placeholder '"+placeholderName+"' found";
                        }

                    }
                } else {
                    placeHolder = this.getPlaceHolder(placeholderName);
                    if(placeHolder){
                        placeHolder.set({content: renderedComponent});
                    }
                    renderedComponent.set(attributes);
                }

            },
            _renderId: function (id) {
                if (id) {
                    this.$el.setAttribute("id", id);
                }else{
                    this.$el.removeAttribute("id");
                }

            }
        });
    }
);<|endoftext|>


<commit_before>define(['jquery'], function ($) {
    var CKEDITOR = window.CKEDITOR;

    // Buttons
    var $a = $('.cke_toolbox_main').find('.cke_button, .cke_combo_button');
    $a.each(function (i, el) {
        var $el = $(el);
        $el.on('keydown blur focus click', function (e) {
            e.preventDefault();
            var attr = $(el).attr('on'+e.type);
            if (!attr) { return; }
            if (e.type === "blur") { return false; }
            var reg = /CKEDITOR.tools.callFunction\(([0-9]+),(this|event)\);return false;/;
            var m = attr.match(reg);
            if (!m) { return; }
            var f = m[1];
            var arg = m[2] === "this" ? el : e.originalEvent;
            CKEDITOR.tools.callFunction(Number(f), arg);
        });
    });

    // Dropdown menus

    var frameTpl = CKEDITOR.getTemplate('panel-frame');
    var panelTpl = CKEDITOR.getTemplate('panel');
    var frameDocTpl = CKEDITOR.addTemplate( 'panel-frame-inner-csp', '<!DOCTYPE html>' +
    '' +
        '{css}' +
        '' +
    '<\/html>' );
    CKEDITOR.ui.panel.prototype.render = function( editor, output ) {
        var data = {
            editorId: editor.id,
            id: this.id,
            langCode: editor.langCode,
            dir: editor.lang.dir,
            cls: this.className,
            frame: '',
            env: CKEDITOR.env.cssClass,
            'z-index': editor.config.baseFloatZIndex + 1
        };

        this.getHolderElement = function() {
            var holder = this._.holder;

            if ( !holder ) {
                if ( this.isFramed ) {
                    var iframe = this.document.getById( this.id + '_frame' ),
                        parentDiv = iframe.getParent(),
                        doc = iframe.getFrameDocument();

                    // Make it scrollable on iOS. (https://dev.ckeditor.com/ticket/8308)
                    if (CKEDITOR.env.iOS) {
                        parentDiv.setStyles( {
                            'overflow': 'scroll',
                            '-webkit-overflow-scrolling': 'touch'
                        } );
                    }

                    var onLoad = CKEDITOR.tools.addFunction( CKEDITOR.tools.bind( function() {
                        this.isLoaded = true;
                        if ( this.onLoad ) {
                            this.onLoad();
                        }
                    }, this ) );

                    doc.write( frameDocTpl.output( CKEDITOR.tools.extend( {
                        css: CKEDITOR.tools.buildStyleHtml( this.css )
                    }, data ) ) );

                    var that = this;
                    $(iframe.$).on('load', function () {
                        that.isLoaded = true;
                        if (that.onLoad) {
                            that.onLoad();
                        }
                    }).contents().find('body').on('click dragstart', '.cke_button, a.cke_colormore, a.cke_colorbox, .cke_colorauto, .cke_combo_button, .cke_panel_listItem a', function (e) {
                        e.preventDefault();
                        if (e.type === 'dragstart') { return false; }
                        var attr = $(e.currentTarget).attr('onclick');
                        var reg = /CKEDITOR.tools.callFunction\(([0-9]+),'?([A-Za-z0-9 ?]+)'?(,'([A-Za-z0-9 ]+)')?\);/;
                        var match = attr.match(reg);
                        if (!match) { return; }
                        var f = match[1];
                        var el = match[2] !== "null" ? match[2] : null;
                        CKEDITOR.tools.callFunction(Number(f), el, match[4]);
                    });

                    // Register the CKEDITOR global.
                    var win = doc.getWindow();
                    win.$.CKEDITOR = CKEDITOR;

                    // Arrow keys for scrolling is only preventable with 'keypress' event in Opera (https://dev.ckeditor.com/ticket/4534).
                    doc.on( 'keydown', function( evt ) {
                        var keystroke = evt.data.getKeystroke(),
                            dir = this.document.getById( this.id ).getAttribute( 'dir' );

                        // Arrow left and right should use native behaviour inside input element
                        if ( evt.data.getTarget().getName() === 'input' && ( keystroke === 37 || keystroke === 39 ) ) {
                            return;
                        }
                        // Delegate key processing to block.
                        if ( this._.onKeyDown && this._.onKeyDown( keystroke ) === false ) {
                            if ( !( evt.data.getTarget().getName() === 'input' && keystroke === 32 ) ) {
                                // Don't prevent space when is pressed on a input filed.
                                evt.data.preventDefault();
                            }
                            return;
                        }

                        // ESC/ARROW-LEFT(ltr) OR ARROW-RIGHT(rtl)
                        if ( keystroke === 27 || keystroke === ( dir === 'rtl' ? 39 : 37 ) ) {
                            if ( this.onEscape && this.onEscape( keystroke ) === false ) {
                                evt.data.preventDefault();
                            }
                        }
                    }, this );

                    holder = doc.getBody();
                    holder.unselectable();
                    if (CKEDITOR.env.air) { CKEDITOR.tools.callFunction( onLoad ); }
                } else {
                    holder = this.document.getById( this.id );
                }

                this._.holder = holder;
            }

            return holder;
        };

        if ( this.isFramed ) {
            // With IE, the custom domain has to be taken care at first,
            // for other browers, the 'src' attribute should be left empty to
            // trigger iframe's 'load' event.
            var src =
                CKEDITOR.env.air ? 'javascript:void(0)' : // jshint ignore:line
                ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) ? 'javascript:void(function(){' + encodeURIComponent( // jshint ignore:line
                    'document.open();' +
                    // In IE, the document domain must be set any time we call document.open().
                    '(' + CKEDITOR.tools.fixDomain + ')();' +
                    'document.close();'
                ) + '}())' :
                '';

            data.frame = frameTpl.output( {
                id: this.id + '_frame',
                src: src
            } );
        }

        var html = panelTpl.output( data );

        if ( output ) { output.push( html ); }

        return html;
    };

    // Mathjax

    if ( !( CKEDITOR.env.ie && CKEDITOR.env.version === 8 ) ) {
        CKEDITOR.plugins.mathjax.frameWrapper = function( iFrame, editor ) {

            var update = function () {}; // Placeholder
            var buffer, preview, value, newValue,
                doc = iFrame.getFrameDocument(),

                // Is MathJax loaded and ready to work.
                isInit = false,

                // Is MathJax parsing Tex.
                isRunning = false,

                // Function called when MathJax is loaded.
                loadedHandler = CKEDITOR.tools.addFunction( function() {
                    preview = doc.getById( 'preview' );
                    buffer = doc.getById( 'buffer' );
                    isInit = true;

                    if ( newValue ) { update(); }

                    // Private! For test usage only.
                    CKEDITOR.fire( 'mathJaxLoaded', iFrame );
                } ),

                // Function called when MathJax finish his job.
                updateDoneHandler = CKEDITOR.tools.addFunction( function() {
                    CKEDITOR.plugins.mathjax.copyStyles( iFrame, preview );

                    preview.setHtml( buffer.getHtml() );

                    editor.fire( 'lockSnapshot' );

                    iFrame.setStyles( {
                        height: 0,
                        width: 0
                    } );

                    // Set iFrame dimensions.
                    var height = Math.max( doc.$.body.offsetHeight, doc.$.documentElement.offsetHeight ),
                        width = Math.max( preview.$.offsetWidth, doc.$.body.scrollWidth );

                    iFrame.setStyles( {
                        height: height + 'px',
                        width: width + 'px'
                    } );

                    editor.fire( 'unlockSnapshot' );

                    // Private! For test usage only.
                    CKEDITOR.fire( 'mathJaxUpdateDone', iFrame );

                    // If value changed in the meantime update it again.
                    if ( value !== newValue ) {
                        update();
                    } else {
                        isRunning = false;
                    }
                } );

            // Run MathJax parsing Tex.
            update = function () {
                isRunning = true;

                value = newValue;

                editor.fire( 'lockSnapshot' );

                buffer.setHtml( value );

                // Set loading indicator.
                preview.setHtml( '' );

                iFrame.setStyles( {
                    height: '16px',
                    width: '16px',
                    display: 'inline',
                    'vertical-align': 'middle'
                } );

                editor.fire( 'unlockSnapshot' );

                // Run MathJax.
                doc.getWindow().$.update( value );
            };

            var load = function () {
                doc = iFrame.getFrameDocument();

                if ( doc.getById( 'preview' ) ) { return; }

                // Because of IE9 bug in a src attribute can not be javascript
                // when you undo (https://dev.ckeditor.com/ticket/10930). If you have iFrame with javascript in src
                // and call insertBefore on such element then IE9 will see crash.
                if ( CKEDITOR.env.ie ) { iFrame.removeAttribute( 'src' ); }

                doc.write( '<!DOCTYPE html>' +
                            '' +
                            '' +
                                '<meta charset="utf-8">' +
                                // Load MathJax lib.
                                '' +
                            '' +
                            '' +
                                '' +

                                // Render everything here and after that copy it to the preview.
                                '' +
                            '' +
                            '' );
                iFrame.$.contentWindow.mathjax_loaded = loadedHandler;
                iFrame.$.contentWindow.mathjax_done = updateDoneHandler;
            };

            iFrame.on( 'load', load );
            load();

            return {
                /**
                 * Sets the TeX value to be displayed in the `iframe` element inside
                 * the editor. This function will activate the MathJax
                 * library which interprets TeX expressions and converts them into
                 * their representation that is displayed in the editor.
                 *
                 * @param {String} value TeX string.
                 */
                setValue: function( value ) {
                    newValue = CKEDITOR.tools.htmlEncode( value );

                    if ( isInit && !isRunning ) {
                        update();
                    }
                }
            };
        };
    }

});
<commit_msg>Fix context menu csp in pads<commit_after>define(['jquery'], function ($) {
    var CKEDITOR = window.CKEDITOR;

    // Buttons
    var $a = $('.cke_toolbox_main').find('.cke_button, .cke_combo_button');
    $a.each(function (i, el) {
        var $el = $(el);
        $el.on('keydown blur focus click', function (e) {
            e.preventDefault();
            var attr = $(el).attr('on'+e.type);
            if (!attr) { return; }
            if (e.type === "blur") { return false; }
            var reg = /CKEDITOR.tools.callFunction\(([0-9]+),(this|event)\);return false;/;
            var m = attr.match(reg);
            if (!m) { return; }
            var f = m[1];
            var arg = m[2] === "this" ? el : e.originalEvent;
            CKEDITOR.tools.callFunction(Number(f), arg);
        });
    });

    // Dropdown menus

    var frameTpl = CKEDITOR.getTemplate('panel-frame');
    var panelTpl = CKEDITOR.getTemplate('panel');
    var frameDocTpl = CKEDITOR.addTemplate( 'panel-frame-inner-csp', '<!DOCTYPE html>' +
    '' +
        '{css}' +
        '' +
    '<\/html>' );
    CKEDITOR.ui.panel.prototype.render = function( editor, output ) {
        var data = {
            editorId: editor.id,
            id: this.id,
            langCode: editor.langCode,
            dir: editor.lang.dir,
            cls: this.className,
            frame: '',
            env: CKEDITOR.env.cssClass,
            'z-index': editor.config.baseFloatZIndex + 1
        };

        this.getHolderElement = function() {
            var holder = this._.holder;

            if ( !holder ) {
                if ( this.isFramed ) {
                    var iframe = this.document.getById( this.id + '_frame' ),
                        parentDiv = iframe.getParent(),
                        doc = iframe.getFrameDocument();

                    // Make it scrollable on iOS. (https://dev.ckeditor.com/ticket/8308)
                    if (CKEDITOR.env.iOS) {
                        parentDiv.setStyles( {
                            'overflow': 'scroll',
                            '-webkit-overflow-scrolling': 'touch'
                        } );
                    }

                    var onLoad = CKEDITOR.tools.addFunction( CKEDITOR.tools.bind( function() {
                        this.isLoaded = true;
                        if ( this.onLoad ) {
                            this.onLoad();
                        }
                    }, this ) );

                    doc.write( frameDocTpl.output( CKEDITOR.tools.extend( {
                        css: CKEDITOR.tools.buildStyleHtml( this.css )
                    }, data ) ) );

                    var that = this;
                    $(iframe.$).on('load', function () {
                        that.isLoaded = true;
                        if (that.onLoad) {
                            that.onLoad();
                        }
                    }).contents().find('body').on('click dragstart mouseover mouseout', '.cke_button, a.cke_colormore, a.cke_colorbox, .cke_colorauto, .cke_combo_button, .cke_panel_listItem a, a.cke_menubutton', function (e) {
                        e.preventDefault();
                        if (e.type === 'dragstart') { return false; }
                        var attr = $(e.currentTarget).attr('on'+e.type);
                        if (!attr) { return; }
                        var reg = /CKEDITOR.tools.callFunction\(([0-9]+),'?([A-Za-z0-9 ?]+)'?(,'([A-Za-z0-9 ]+)')?\);/;
                        var match = attr.match(reg);
                        if (!match) { return; }
                        var f = match[1];
                        var el = match[2] !== "null" ? match[2] : null;
                        CKEDITOR.tools.callFunction(Number(f), el, match[4]);
                    });

                    // Register the CKEDITOR global.
                    var win = doc.getWindow();
                    win.$.CKEDITOR = CKEDITOR;

                    // Arrow keys for scrolling is only preventable with 'keypress' event in Opera (https://dev.ckeditor.com/ticket/4534).
                    doc.on( 'keydown', function( evt ) {
                        var keystroke = evt.data.getKeystroke(),
                            dir = this.document.getById( this.id ).getAttribute( 'dir' );

                        // Arrow left and right should use native behaviour inside input element
                        if ( evt.data.getTarget().getName() === 'input' && ( keystroke === 37 || keystroke === 39 ) ) {
                            return;
                        }
                        // Delegate key processing to block.
                        if ( this._.onKeyDown && this._.onKeyDown( keystroke ) === false ) {
                            if ( !( evt.data.getTarget().getName() === 'input' && keystroke === 32 ) ) {
                                // Don't prevent space when is pressed on a input filed.
                                evt.data.preventDefault();
                            }
                            return;
                        }

                        // ESC/ARROW-LEFT(ltr) OR ARROW-RIGHT(rtl)
                        if ( keystroke === 27 || keystroke === ( dir === 'rtl' ? 39 : 37 ) ) {
                            if ( this.onEscape && this.onEscape( keystroke ) === false ) {
                                evt.data.preventDefault();
                            }
                        }
                    }, this );

                    holder = doc.getBody();
                    holder.unselectable();
                    if (CKEDITOR.env.air) { CKEDITOR.tools.callFunction( onLoad ); }
                } else {
                    holder = this.document.getById( this.id );
                }

                this._.holder = holder;
            }

            return holder;
        };

        if ( this.isFramed ) {
            // With IE, the custom domain has to be taken care at first,
            // for other browers, the 'src' attribute should be left empty to
            // trigger iframe's 'load' event.
            var src =
                CKEDITOR.env.air ? 'javascript:void(0)' : // jshint ignore:line
                ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) ? 'javascript:void(function(){' + encodeURIComponent( // jshint ignore:line
                    'document.open();' +
                    // In IE, the document domain must be set any time we call document.open().
                    '(' + CKEDITOR.tools.fixDomain + ')();' +
                    'document.close();'
                ) + '}())' :
                '';

            data.frame = frameTpl.output( {
                id: this.id + '_frame',
                src: src
            } );
        }

        var html = panelTpl.output( data );

        if ( output ) { output.push( html ); }

        return html;
    };

    // Mathjax

    if ( !( CKEDITOR.env.ie && CKEDITOR.env.version === 8 ) ) {
        CKEDITOR.plugins.mathjax.frameWrapper = function( iFrame, editor ) {

            var update = function () {}; // Placeholder
            var buffer, preview, value, newValue,
                doc = iFrame.getFrameDocument(),

                // Is MathJax loaded and ready to work.
                isInit = false,

                // Is MathJax parsing Tex.
                isRunning = false,

                // Function called when MathJax is loaded.
                loadedHandler = CKEDITOR.tools.addFunction( function() {
                    preview = doc.getById( 'preview' );
                    buffer = doc.getById( 'buffer' );
                    isInit = true;

                    if ( newValue ) { update(); }

                    // Private! For test usage only.
                    CKEDITOR.fire( 'mathJaxLoaded', iFrame );
                } ),

                // Function called when MathJax finish his job.
                updateDoneHandler = CKEDITOR.tools.addFunction( function() {
                    CKEDITOR.plugins.mathjax.copyStyles( iFrame, preview );

                    preview.setHtml( buffer.getHtml() );

                    editor.fire( 'lockSnapshot' );

                    iFrame.setStyles( {
                        height: 0,
                        width: 0
                    } );

                    // Set iFrame dimensions.
                    var height = Math.max( doc.$.body.offsetHeight, doc.$.documentElement.offsetHeight ),
                        width = Math.max( preview.$.offsetWidth, doc.$.body.scrollWidth );

                    iFrame.setStyles( {
                        height: height + 'px',
                        width: width + 'px'
                    } );

                    editor.fire( 'unlockSnapshot' );

                    // Private! For test usage only.
                    CKEDITOR.fire( 'mathJaxUpdateDone', iFrame );

                    // If value changed in the meantime update it again.
                    if ( value !== newValue ) {
                        update();
                    } else {
                        isRunning = false;
                    }
                } );

            // Run MathJax parsing Tex.
            update = function () {
                isRunning = true;

                value = newValue;

                editor.fire( 'lockSnapshot' );

                buffer.setHtml( value );

                // Set loading indicator.
                preview.setHtml( '' );

                iFrame.setStyles( {
                    height: '16px',
                    width: '16px',
                    display: 'inline',
                    'vertical-align': 'middle'
                } );

                editor.fire( 'unlockSnapshot' );

                // Run MathJax.
                doc.getWindow().$.update( value );
            };

            var load = function () {
                doc = iFrame.getFrameDocument();

                if ( doc.getById( 'preview' ) ) { return; }

                // Because of IE9 bug in a src attribute can not be javascript
                // when you undo (https://dev.ckeditor.com/ticket/10930). If you have iFrame with javascript in src
                // and call insertBefore on such element then IE9 will see crash.
                if ( CKEDITOR.env.ie ) { iFrame.removeAttribute( 'src' ); }

                doc.write( '<!DOCTYPE html>' +
                            '' +
                            '' +
                                '<meta charset="utf-8">' +
                                // Load MathJax lib.
                                '' +
                            '' +
                            '' +
                                '' +

                                // Render everything here and after that copy it to the preview.
                                '' +
                            '' +
                            '' );
                iFrame.$.contentWindow.mathjax_loaded = loadedHandler;
                iFrame.$.contentWindow.mathjax_done = updateDoneHandler;
            };

            iFrame.on( 'load', load );
            load();

            return {
                /**
                 * Sets the TeX value to be displayed in the `iframe` element inside
                 * the editor. This function will activate the MathJax
                 * library which interprets TeX expressions and converts them into
                 * their representation that is displayed in the editor.
                 *
                 * @param {String} value TeX string.
                 */
                setValue: function( value ) {
                    newValue = CKEDITOR.tools.htmlEncode( value );

                    if ( isInit && !isRunning ) {
                        update();
                    }
                }
            };
        };
    }

});
<|endoftext|>


<commit_before>Version = { id: '47038e7' };
<commit_msg>Bump up version<commit_after>Version = { id: 'dbe5bf3' };
<|endoftext|>


<commit_before>'use strict'

;(async(function* (){
  // Regex to test if code is a url and only one line...

  // Utilities
  let $ = (selector, fragment = document) => fragment.querySelector(selector)
  let $$ = (selector, fragment = document) => fragment.querySelectorAll(selector)
  let setVal = file => file.text().then(txt => (_code.value = txt)).catch(()=>{alert(1)})
  let stop = evt => evt && evt.stopPropagation(evt.preventDefault())
  let {plugins} = yield app.getPlugins
  let loader = $('#loader')
  let _alert = $('#_alert')
  let uuid = 0

  app.filesDroped = evt => setVal(evt.dataTransfer.files[0], stop(evt))

  function displayContent(evt, content) {
    stop(evt)
    $overview.innerHTML = ''
    loader.hidden = false

    app.get(location.pathname).then(res => {
      loader.hidden = true

      if (!res.ok) {
        _alert.showModal()
        $('p', _alert).innerText = res.data.message
        $('code', _alert).innerText = res.data.stack
        return
      }

      let fragment = new DocumentFragment
      let content = $linkItem.content
      let a = content.querySelector('a')
      let img = content.querySelector('img')
      let poster = content.querySelector('.poster')

      a.style.backgroundImage = ``

      if (res.data.video) {
        let video = document.createElement('video')
        video.controls = true
        video.className = 'video-js vjs-default-skin'
        $overview.appendChild(video)
        let player = videojs(video, {
          plugins: { airplayButton: {} }
        })
        player.fluid(true)
        player.qualityLevels()
        player.src(res.data.video.source)
        player.poster(res.data.video.poster)
        window.player = player
      }

      if (res.data.links) {
        for (let link of res.data.links) {
          img.src = link.poster || 'https://dummyimage.com/480x270/000/fff&text=' + link.title
          a.innerText = link.title
          a.href = '/' + res.plugin + link.src
          fragment.appendChild(document.importNode($linkItem.content, true))
        }
      }
      $overview.appendChild(fragment)
    })
  }

  app.loadPlugin = evt => setVal(evt.target.files[0])

  app.loadPluginPage = evt => {
    stop(evt)

    var fragment = new DocumentFragment()
    fragment.appendChild(document.importNode($pluginForm.content, true))

    let a = $('a', $pluginItem.content)
    let del = $('button', $pluginItem.content)
    let section = $('section', $pluginItem.content)
    let {content} = $pluginItem

    for (let plugin of plugins) {
      section.dataset.name = del.dataset.name = a.innerText = plugin.name
      a.href = `/${plugin.name}/`
      fragment.appendChild(document.importNode(content, true))
    }

    $overview.innerHTML = ''
    $overview.appendChild(fragment)
  }

  app.loadHomePage = evt => {
    stop(evt)
    $overview.innerHTML = ''

    for (let plugin of plugins) {
      app.get(`/${plugin.name}/`).then(res => {
        let fragment = new DocumentFragment
        let content = $linkItem.content
        let a = content.querySelector('a')
        content.querySelector('img').src = ''
        let poster = content.querySelector('.poster')
        let container = document.importNode($horizontalMenu.content, true)
        let section = $('ul', container)
        $('h3', container).innerText = plugin.name

        for (let link of res.data.links) {
          let text = '' + link.title
          a.style.backgroundImage = `url("https://dummyimage.com/480x270/000/fff&text=${text}")`
          a.style.backgroundImage = `url(${link.poster})`
          a.innerText = link.title
          a.href = '/' +plugin.name + link.src
          section.appendChild(document.importNode($linkItem.content, true))
        }
        $overview.appendChild(container)
      })
    }
  }

  app.submitPlugin = evt => {
    stop(evt)
    app.addPlugin(evt.target.elements.code.value).then(res => {
      res.ok ? app.loadPluginPage() : alert(res.data.message)
    })
  }

  app._updateSettings = event => {
    stop(event)

    let fd = new FormData(event.target)
    app.updateSettings($settingsDialog.dataset.name, [...fd])
  }

  app._openSettings = event => {
    let section = event.target.closest('section')
    let pluginName = section.dataset.name
    app.getSettings(pluginName).then(({settings}) => {
      let dialog = window.$settingsDialog
      let section = $('section', dialog)
      dialog.dataset.name = pluginName
      dialog.showModal()
      $('header h3', dialog).innerText = 'Settings - ' + pluginName
      section.innerHTML = ''
      settings.forEach((field, index) => {
        let container = document.createElement('div')
        let label = document.createElement('label')
        let input = document.createElement('input')
        container.className = 'input-container'

        input.id = 'input_' + (uuid++)
        input.autofocus = !index
        input.type = field.type
        input.defaultValue = field.defaultValue
        input.value = field.value
        input.name = field.name
        input.placeholder = ' '

        label.innerText = field.placeholder
        label.htmlFor = input.id

        container.appendChild(input)
        container.appendChild(label)
        section.appendChild(container)
      })

    })
  }

  app._delete = event => {
    let section = event.target.closest('section')
    let pluginName = section.dataset.name
    app.delete(pluginName)
    section.remove()
  }

  let nav = () => {
    switch (location.pathname) {
      case '/': app.loadHomePage(); break;
      case '/plugins': app.loadPluginPage(); break;
      default: displayContent(); break;
    }
  }

  document.onclick = evt => {
    if (evt.target.matches('a')) {
      history.pushState({}, 'fff', evt.target.href)
      nav(stop(evt))
    }
  }

  window.onpopstate = nav; nav()

}))();
<commit_msg>Renamed placeholder to label<commit_after>'use strict'

;(async(function* (){
  // Regex to test if code is a url and only one line...

  // Utilities
  let $ = (selector, fragment = document) => fragment.querySelector(selector)
  let $$ = (selector, fragment = document) => fragment.querySelectorAll(selector)
  let setVal = file => file.text().then(txt => (_code.value = txt)).catch(()=>{alert(1)})
  let stop = evt => evt && evt.stopPropagation(evt.preventDefault())
  let {plugins} = yield app.getPlugins
  let loader = $('#loader')
  let _alert = $('#_alert')
  let uuid = 0

  app.filesDroped = evt => setVal(evt.dataTransfer.files[0], stop(evt))

  function displayContent(evt, content) {
    stop(evt)
    $overview.innerHTML = ''
    loader.hidden = false

    app.get(location.pathname).then(res => {
      loader.hidden = true

      if (!res.ok) {
        _alert.showModal()
        $('p', _alert).innerText = res.data.message
        $('code', _alert).innerText = res.data.stack
        return
      }

      let fragment = new DocumentFragment
      let content = $linkItem.content
      let a = content.querySelector('a')
      let img = content.querySelector('img')
      let poster = content.querySelector('.poster')

      a.style.backgroundImage = ``

      if (res.data.video) {
        let video = document.createElement('video')
        video.controls = true
        video.className = 'video-js vjs-default-skin'
        $overview.appendChild(video)
        let player = videojs(video, {
          plugins: { airplayButton: {} }
        })
        player.fluid(true)
        player.qualityLevels()
        player.src(res.data.video.source)
        player.poster(res.data.video.poster)
        window.player = player
      }

      if (res.data.links) {
        for (let link of res.data.links) {
          img.src = link.poster || 'https://dummyimage.com/480x270/000/fff&text=' + link.title
          a.innerText = link.title
          a.href = '/' + res.plugin + link.src
          fragment.appendChild(document.importNode($linkItem.content, true))
        }
      }
      $overview.appendChild(fragment)
    })
  }

  app.loadPlugin = evt => setVal(evt.target.files[0])

  app.loadPluginPage = evt => {
    stop(evt)

    var fragment = new DocumentFragment()
    fragment.appendChild(document.importNode($pluginForm.content, true))

    let a = $('a', $pluginItem.content)
    let del = $('button', $pluginItem.content)
    let section = $('section', $pluginItem.content)
    let {content} = $pluginItem

    for (let plugin of plugins) {
      section.dataset.name = del.dataset.name = a.innerText = plugin.name
      a.href = `/${plugin.name}/`
      fragment.appendChild(document.importNode(content, true))
    }

    $overview.innerHTML = ''
    $overview.appendChild(fragment)
  }

  app.loadHomePage = evt => {
    stop(evt)
    $overview.innerHTML = ''

    for (let plugin of plugins) {
      app.get(`/${plugin.name}/`).then(res => {
        let fragment = new DocumentFragment
        let content = $linkItem.content
        let a = content.querySelector('a')
        content.querySelector('img').src = ''
        let poster = content.querySelector('.poster')
        let container = document.importNode($horizontalMenu.content, true)
        let section = $('ul', container)
        $('h3', container).innerText = plugin.name

        for (let link of res.data.links) {
          let text = '' + link.title
          a.style.backgroundImage = `url("https://dummyimage.com/480x270/000/fff&text=${text}")`
          a.style.backgroundImage = `url(${link.poster})`
          a.innerText = link.title
          a.href = '/' +plugin.name + link.src
          section.appendChild(document.importNode($linkItem.content, true))
        }
        $overview.appendChild(container)
      })
    }
  }

  app.submitPlugin = evt => {
    stop(evt)
    app.addPlugin(evt.target.elements.code.value).then(res => {
      res.ok ? app.loadPluginPage() : alert(res.data.message)
    })
  }

  app._updateSettings = event => {
    stop(event)

    let fd = new FormData(event.target)
    app.updateSettings($settingsDialog.dataset.name, [...fd])
  }

  app._openSettings = event => {
    let section = event.target.closest('section')
    let pluginName = section.dataset.name
    app.getSettings(pluginName).then(({settings}) => {
      let dialog = window.$settingsDialog
      let section = $('section', dialog)
      dialog.dataset.name = pluginName
      dialog.showModal()
      $('header h3', dialog).innerText = 'Settings - ' + pluginName
      section.innerHTML = ''
      settings.forEach((field, index) => {
        let container = document.createElement('div')
        let label = document.createElement('label')
        let input = document.createElement('input')
        container.className = 'input-container'

        input.id = 'input_' + (uuid++)
        input.autofocus = !index
        input.type = field.type
        input.defaultValue = field.defaultValue
        input.value = field.value
        input.name = field.name
        input.placeholder = ' '

        label.innerText = field.label
        label.htmlFor = input.id

        container.appendChild(input)
        container.appendChild(label)
        section.appendChild(container)
      })

    })
  }

  app._delete = event => {
    let section = event.target.closest('section')
    let pluginName = section.dataset.name
    app.delete(pluginName)
    section.remove()
  }

  let nav = () => {
    switch (location.pathname) {
      case '/': app.loadHomePage(); break;
      case '/plugins': app.loadPluginPage(); break;
      default: displayContent(); break;
    }
  }

  document.onclick = evt => {
    if (evt.target.matches('a')) {
      history.pushState({}, 'fff', evt.target.href)
      nav(stop(evt))
    }
  }

  window.onpopstate = nav; nav()

}))();
<|endoftext|>