<commit_before>require("dotenv").config();
const Discord = require("discord.js");
const ytdl = require("ytdl-core");
const fs = require("fs");
const google = require("googleapis");
const youtube = google.youtube("v3");
const bot = new Discord.Client();

const prefix = "!";
var fortunes = ["It is certain", "It is decidedly so", "Without a doubt", "Yes definitely", "You may rely of it", "As I see it, yes", "Most likely", "Outlook good", "Yes", "Signs point to yes", "Reply hazy try again", "Ask again later", "Better not tell you now", "Cannot predict now", "Conentrate and ask again", "Dont count on it", "My reply is no", "My sources say no", "Outlook not so good", "Very doubtful"];
var dispacter;
var songQueue = [];

var commands = {
    "help": {
        "usage": "<command>",
        "description": "Gives you a list of commands you can use or details on specific command(s)",
        "process": function(message, args){
            if(args.length === 0){
                var commandKeys = Object.keys(commands);
                var commandList = "";
                for(var i = 0; i < commandKeys.length - 1; i++){
                    commandList += `\`${commandKeys[i]}\`, `;
                }
                commandList += `and \`${commandKeys[commandKeys.length - 1]}\``;
                message.reply("My current commands are: " + commandList);
                message.channel.send(`You can use \`${prefix}help <command>\` to learn more about a command!`);
            } else{
                for(var i = 0; i < args.length; i++){
                    try{
                        message.channel.send(`\`!${args[i]} ${commands[args[i]].usage}\`: ${commands[args[i]].description}`);
                    } catch(e){
                        message.channel.send(`\`!${args[i]}\`: Not a command`);
                    }
                }
            }
        }
    },
    "bot": {
        "usage": "",
        "description": "Tells you information about the bot",
        "process": function(message, args){
            message.reply("I am a discord bot for didney worl who has an appetite for non-nutritive substances");
            message.channel.send("If you have any suggestions or command ideas for me tell @Crumster or your local amin");
        }
    },
    "ping": {
        "usage": "",
        "description": "Pings the bot, useful for seeing if it's alive",
        "process": function(message, args){
            message.reply("Pong :ping_pong:");
        }
    },
    "roll": {
        "usage": "<amount>d<sides>",
        "description": "Rolls a die",
        "process": function(message, args){
            var rolls = [];
            var die = "";
            if(args.length === 0){
                die = "1d6";
                rolls.push(Math.floor(Math.random() * 6 + 1));
            } else{
                var amount = parseInt(args[0].split("d")[0]);
                var sides = parseInt(args[0].split("d")[1]);
                var single = false;
                if(args[0].substring(0, 1) === "d" && Number.isInteger(sides)){
                    rolls.push(Math.floor(Math.random() * sides + 1));
                    single = true;
                }
                if(!single && (!Number.isInteger(amount) || !Number.isInteger(sides))){
                    message.reply("That is not a valid die");
                    return;
                }
                if(amount > 10){
                    message.reply("You cannot roll more than 10 dice at a time");
                    return;
                }
                die = args[0];
                for(var i = 0; i < amount; i++){
                    rolls.push(Math.floor(Math.random() * sides + 1));
                }
            }
            var rollList = "";
            for(var i = 0; i < rolls.length - 1; i++){
                rollList += rolls[i] + ", ";
            }
            rollList += rolls[rolls.length - 1];
            message.reply(`You rolled ${die} :game_die: and got: ${rollList}`);
        }
    },
    "8ball": {
        "usage": "",
        "description": "Asks a magic 8ball for a fortune",
        "process": function(message, args){
            message.reply(fortunes[Math.floor(Math.random() * fortunes.length)]);
        }
    },
    "save": {
        "usage": "<key> <message>",
        "description": "Saves a personalized message with a given key",
        "process": function(message, args){
            message.reply("**Disclaimer:** your message will not be permanantly saved and will delete upon bot restart (for now)");
            if(args.length < 2){
                message.reply(`Save a message with \`${prefix}save <key> <message>\``);
                return;
            }
            var key = args[0];
            var messageToSave = "";
            for(var i = 0; i < args.length - 2; i++){
                messageToSave += args[i + 1] + " ";
            }
            messageToSave += args[args.length - 1];
            fs.readFile("save.json", "utf8", function(err, data){
                if(err) throw err;
                var save = JSON.parse(data);
                if(save[message.author.username] === undefined){
                    save[message.author.username] = {};
                }
                save[message.author.username][key] = messageToSave;
                fs.writeFile("save.json", JSON.stringify(save), "utf8", function(err){
                    if(err) throw err;
                    message.reply(`Your message has been saved as \`${key}\`! :tada:`);
                });
            });
        }
    },
    "recall": {
        "usage": "<key>",
        "description": "Lists your saved messages or recalls a saved message with a given key",
        "process": function(message, args){
            fs.readFile("save.json", "utf8", function(err, data){
                if(err) throw err;
                var save = JSON.parse(data);
                if(args.length === 0){
                    var messageKeys;
                    var savedMessages = "";
                    try{
                        messageKeys = Object.keys(save[message.author.username]);
                    } catch(e){
                        message.reply("You have no saved messages, try saving one!");
                        return;
                    }
                    if(messageKeys.length === 0){
                        message.reply("You have no saved messages, try saving one!");
                        return;
                    }
                    for(var i = 0; i < messageKeys.length - 1; i++){
                        savedMessages += messageKeys[i] + ", ";
                    }
                    savedMessages += messageKeys[messageKeys.length - 1];
                    message.reply("Your saved messages are: " + savedMessages);
                } else{
                    var key = args[0];
                    var recalledMessage = save[message.author.username][key];
                    if(recalledMessage === undefined){
                        message.reply(`You don't have a saved message with the key \`${key}\``);
                    } else{
                        message.reply(recalledMessage);
                    }
                }
            });
        }
    },
    "delete": {
        "usage": "<key>",
        "description": "Deletes a saved message with a given key",
        "process": function(message, args){
            fs.readFile("save.json", "utf8", function(err, data){
                if(err) throw err;
                var save = JSON.parse(data);
                if(args.length === 0){
                    message.reply(`Delete a saved message with \`${prefix}delete <key>\``);
                    return;
                } else{
                    var key = args[0];
                    if(save[message.author.username][key] === undefined){
                        message.reply(`You don't have a saved message with the key \`${key}\``);
                    } else{
                        delete save[message.author.username][key];
                        fs.writeFile("save.json", JSON.stringify(save), "utf8", function(err){
                            if(err) throw err;
                            message.reply(`Your message \`${key}\` has been deleted! :tada:`);
                        });
                    }
                }
            });
        }
    },
    "insult": {
        "usage": "",
        "description": "Call the bot to your voice channel to deliver a special insult",
        "process": function(message, args){
            message.reply("There are currently no insults :sob:");
        }
    },
    "addsong": {
        "usage": "<link>",
        "description": "Adds a song to the song queue via a youtube link",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                addSong(message, args[0]);
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "search":{
        "usage": "<query>",
        "description": "Searches for a youtube video to add to the song queue",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                if(args.length > 0){
                    var query = "";
                    for(var i = 0; i < args.length - 1; i++){
                        query += args[i] + " "
                    }
                    query += " " + args[args.length - 1];
                    var results = youtube.search.list({
                        "key": process.env.GOOGLEAPIKEY,
                        "q": query,
                        "type": "video",
                        "maxResults": "1",
                        "part": "snippet"
                    }, function(err, data){
                        if(err){
                            message.reply("There was an error searching for your song :cry:");
                            console.log("Error: " + err);
                        }
                        if(data){
                            addSong(message, "https://www.youtube.com/watch?v=" + data.items[0].id.videoId);
                        }
                    });
                } else{
                    message.reply(`You can search for a song with \`${prefix}search <query>\``);
                }
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "play": {
        "usage": "",
        "description": "Resumes the current song",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                if(songQueue.length > 0){
                    if(dispacter.paused){
                        dispacter.resume();
                        message.reply("Song resumed! :play_pause:");
                    } else{
                        message.reply("Song is already playing");
                    }
                } else{
                    message.reply("No song is in the queue");
                }
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "pause": {
        "usage": "",
        "description": "Pauses the current song",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                if(songQueue.length > 0){
                    if(!dispacter.paused){
                        dispacter.pause();
                        message.reply("Song paused! :pause_button:");
                    } else{
                        message.reply("Song is already paused");
                    }
                } else{
                    message.reply("No song is in the queue");
                }
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "next": {
        "usage": "",
        "description": "Skips to the next song in the queue",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                if(songQueue.length > 0){
                    dispacter.end();
                } else{
                    message.reply("There are no more songs :sob:");
                }
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "clear": {
        "usage": "",
        "description": "Clears the song queue",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                if(songQueue.length === 0){
                    message.reply("There are no songs to clear");
                } else{
                    songQueue = [];
                    dispacter.end();
                    message.reply("The song queue has been cleared");
                }
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "song": {
        "usage": "",
        "description": "Gives you information about the currently playing song",
        "process": function(message, args){
            if(songQueue.length > 0){
                message.reply(`The current song is \`${songQueue[0].title}\` :musical_note:, added by ${songQueue[0].user}`);
            } else{
                message.reply("No song is in the queue");
            }
        }
    },
    "music": {
        "usage": "",
        "description": "Gives you a list of the songs currently in the queue",
        "process": function(message, args){
            if(songQueue.length > 0){
                var songList = "";
                for(var i = 0; i < songQueue.length - 1; i++){
                    songList += `\`${songQueue[i].title}\`\n`;
                }
                songList += `\`${songQueue[songQueue.length - 1].title}\``;
                message.reply("The song queue currently has:\n" + songList);
            } else{
                message.reply("No song is in the queue");
            }
        }
    },
    "printsave": {
        "usage": "",
        "description": "Prints the save.json to the console for temporary saving",
        "process": function(message, args){
            fs.readFile("save.json", "utf8", function(err, data){
                if(err) throw err;
                console.log(JSON.parse(data));
                message.reply("The save file has been printed to the log");
            });
        }
    }
};

var addSong = function(message, url){
    ytdl.getInfo(url, function(err, info){
        if(err){
            message.reply("Sorry I couldn't get info for that song :cry:");
            return;
        }
        var song = {};
        song.title = info.title;
        song.url = url;
        song.user = message.author.username;
        songQueue.push(song);
        message.reply(`I have added \`${info.title}\` to the song queue! :headphones:`);
        if(songQueue.length === 1){
            message.member.voiceChannel.join().then(function(connection){playSong(message, connection)});
        }
    });
}

var playSong = function(message, connection){
    var stream = ytdl(songQueue[0].url, {"filter": "audioonly"});
    dispacter = connection.playStream(stream);
    message.channel.send(`Now playing \`${songQueue[0].title}\` :musical_note:, added by ${songQueue[0].user}`);
    dispacter.on("end", function(){
        songQueue.shift();
        if(songQueue.length === 0){
            message.channel.send("There are no more songs :sob:");
            message.member.voiceChannel.leave();
        } else{
            playSong(message, connection);
        }
    });
}

var checkForCommand = function(message){
    if(!message.author.bot && message.content.startsWith(prefix)){
        var args = message.content.substring(1).split(" ");
        var command = args.splice(0, 1);
        try{
            commands[command].process(message, args);
        } catch(e){
            message.reply("Sorry, that isn't a command yet :sob:");
            message.channel.send(`You can type \`${prefix}help\` to see a list of my commands`);
        }
    }
}

bot.on("ready", function(){console.log("Bot ready!")});
bot.on("disconnect", function(){
    console.log("Bot disconnected!");
    process.exit(1);
});
bot.on("guildMemberAdd", function(member){
    member.guild.defaultChannel.send(`Welcome to the server, ${member}! :smile:`);
    member.guild.defaultChannel.send(`You can type \`${prefix}help\` at anytime to see my commands`);
});
bot.on("message", function(message){checkForCommand(message)});
bot.on("messageUpdate", function(oldMessage, newMessage){checkForCommand(newMessage)});

bot.login(process.env.BOTTOKEN);

fs.readFile("save.json", function(err, data){
    if(err){
        if(err.code === "ENOENT"){
            console.log("save.json does not exist");
            fs.writeFile("save.json", "{}", "utf8", function(err){
                if(err) throw err
                console.log("save.json created");
            });
        } else{
            throw err;
        }
    }
});<commit_msg>Fix recall/delete bug (#16)<commit_after>require("dotenv").config();
const Discord = require("discord.js");
const ytdl = require("ytdl-core");
const fs = require("fs");
const google = require("googleapis");
const youtube = google.youtube("v3");
const bot = new Discord.Client();

const prefix = "!";
var fortunes = ["It is certain", "It is decidedly so", "Without a doubt", "Yes definitely", "You may rely of it", "As I see it, yes", "Most likely", "Outlook good", "Yes", "Signs point to yes", "Reply hazy try again", "Ask again later", "Better not tell you now", "Cannot predict now", "Conentrate and ask again", "Dont count on it", "My reply is no", "My sources say no", "Outlook not so good", "Very doubtful"];
var dispacter;
var songQueue = [];

var commands = {
    "help": {
        "usage": "<command>",
        "description": "Gives you a list of commands you can use or details on specific command(s)",
        "process": function(message, args){
            if(args.length === 0){
                var commandKeys = Object.keys(commands);
                var commandList = "";
                for(var i = 0; i < commandKeys.length - 1; i++){
                    commandList += `\`${commandKeys[i]}\`, `;
                }
                commandList += `and \`${commandKeys[commandKeys.length - 1]}\``;
                message.reply("My current commands are: " + commandList);
                message.channel.send(`You can use \`${prefix}help <command>\` to learn more about a command!`);
            } else{
                for(var i = 0; i < args.length; i++){
                    try{
                        message.channel.send(`\`!${args[i]} ${commands[args[i]].usage}\`: ${commands[args[i]].description}`);
                    } catch(e){
                        message.channel.send(`\`!${args[i]}\`: Not a command`);
                    }
                }
            }
        }
    },
    "bot": {
        "usage": "",
        "description": "Tells you information about the bot",
        "process": function(message, args){
            message.reply("I am a discord bot for didney worl who has an appetite for non-nutritive substances");
            message.channel.send("If you have any suggestions or command ideas for me tell @Crumster or your local amin");
        }
    },
    "ping": {
        "usage": "",
        "description": "Pings the bot, useful for seeing if it's alive",
        "process": function(message, args){
            message.reply("Pong :ping_pong:");
        }
    },
    "roll": {
        "usage": "<amount>d<sides>",
        "description": "Rolls a die",
        "process": function(message, args){
            var rolls = [];
            var die = "";
            if(args.length === 0){
                die = "1d6";
                rolls.push(Math.floor(Math.random() * 6 + 1));
            } else{
                var amount = parseInt(args[0].split("d")[0]);
                var sides = parseInt(args[0].split("d")[1]);
                var single = false;
                if(args[0].substring(0, 1) === "d" && Number.isInteger(sides)){
                    rolls.push(Math.floor(Math.random() * sides + 1));
                    single = true;
                }
                if(!single && (!Number.isInteger(amount) || !Number.isInteger(sides))){
                    message.reply("That is not a valid die");
                    return;
                }
                if(amount > 10){
                    message.reply("You cannot roll more than 10 dice at a time");
                    return;
                }
                die = args[0];
                for(var i = 0; i < amount; i++){
                    rolls.push(Math.floor(Math.random() * sides + 1));
                }
            }
            var rollList = "";
            for(var i = 0; i < rolls.length - 1; i++){
                rollList += rolls[i] + ", ";
            }
            rollList += rolls[rolls.length - 1];
            message.reply(`You rolled ${die} :game_die: and got: ${rollList}`);
        }
    },
    "8ball": {
        "usage": "",
        "description": "Asks a magic 8ball for a fortune",
        "process": function(message, args){
            message.reply(fortunes[Math.floor(Math.random() * fortunes.length)]);
        }
    },
    "save": {
        "usage": "<key> <message>",
        "description": "Saves a personalized message with a given key",
        "process": function(message, args){
            message.reply("**Disclaimer:** your message will not be permanantly saved and will delete upon bot restart (for now)");
            if(args.length < 2){
                message.reply(`Save a message with \`${prefix}save <key> <message>\``);
                return;
            }
            var key = args[0];
            var messageToSave = "";
            for(var i = 0; i < args.length - 2; i++){
                messageToSave += args[i + 1] + " ";
            }
            messageToSave += args[args.length - 1];
            fs.readFile("save.json", "utf8", function(err, data){
                if(err) throw err;
                var save = JSON.parse(data);
                if(save[message.author.username] === undefined){
                    save[message.author.username] = {};
                }
                save[message.author.username][key] = messageToSave;
                fs.writeFile("save.json", JSON.stringify(save), "utf8", function(err){
                    if(err) throw err;
                    message.reply(`Your message has been saved as \`${key}\`! :tada:`);
                });
            });
        }
    },
    "recall": {
        "usage": "<key>",
        "description": "Lists your saved messages or recalls a saved message with a given key",
        "process": function(message, args){
            fs.readFile("save.json", "utf8", function(err, data){
                if(err) throw err;
                var save = JSON.parse(data);
                if(args.length === 0){
                    var messageKeys;
                    var savedMessages = "";
                    try{
                        messageKeys = Object.keys(save[message.author.username]);
                    } catch(e){
                        message.reply("You have no saved messages, try saving one!");
                        return;
                    }
                    if(messageKeys.length === 0){
                        message.reply("You have no saved messages, try saving one!");
                        return;
                    }
                    for(var i = 0; i < messageKeys.length - 1; i++){
                        savedMessages += messageKeys[i] + ", ";
                    }
                    savedMessages += messageKeys[messageKeys.length - 1];
                    message.reply("Your saved messages are: " + savedMessages);
                } else{
                    var key = args[0];
                    var recalledMessage;
                    try{
                        recalledMessage = save[message.author.username][key];
                    } catch(e){
                        message.reply(`You don't have a saved message with the key \`${key}\``);
                        return;
                    }
                    message.reply(recalledMessage);
                }
            });
        }
    },
    "delete": {
        "usage": "<key>",
        "description": "Deletes a saved message with a given key",
        "process": function(message, args){
            fs.readFile("save.json", "utf8", function(err, data){
                if(err) throw err;
                var save = JSON.parse(data);
                if(args.length === 0){
                    message.reply(`Delete a saved message with \`${prefix}delete <key>\``);
                    return;
                } else{
                    var key = args[0];
                    try{
                        delete save[message.author.username][key];
                    } catch(e){
                        message.reply(`You don't have a saved message with the key \`${key}\``);
                        return;
                    }
                    fs.writeFile("save.json", JSON.stringify(save), "utf8", function(err){
                        if(err) throw err;
                        message.reply(`Your message \`${key}\` has been deleted! :tada:`);
                    });
                }
            });
        }
    },
    "insult": {
        "usage": "",
        "description": "Call the bot to your voice channel to deliver a special insult",
        "process": function(message, args){
            message.reply("There are currently no insults :sob:");
        }
    },
    "addsong": {
        "usage": "<link>",
        "description": "Adds a song to the song queue via a youtube link",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                addSong(message, args[0]);
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "search":{
        "usage": "<query>",
        "description": "Searches for a youtube video to add to the song queue",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                if(args.length > 0){
                    var query = "";
                    for(var i = 0; i < args.length - 1; i++){
                        query += args[i] + " "
                    }
                    query += " " + args[args.length - 1];
                    var results = youtube.search.list({
                        "key": process.env.GOOGLEAPIKEY,
                        "q": query,
                        "type": "video",
                        "maxResults": "1",
                        "part": "snippet"
                    }, function(err, data){
                        if(err){
                            message.reply("There was an error searching for your song :cry:");
                            console.log("Error: " + err);
                        }
                        if(data){
                            addSong(message, "https://www.youtube.com/watch?v=" + data.items[0].id.videoId);
                        }
                    });
                } else{
                    message.reply(`You can search for a song with \`${prefix}search <query>\``);
                }
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "play": {
        "usage": "",
        "description": "Resumes the current song",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                if(songQueue.length > 0){
                    if(dispacter.paused){
                        dispacter.resume();
                        message.reply("Song resumed! :play_pause:");
                    } else{
                        message.reply("Song is already playing");
                    }
                } else{
                    message.reply("No song is in the queue");
                }
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "pause": {
        "usage": "",
        "description": "Pauses the current song",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                if(songQueue.length > 0){
                    if(!dispacter.paused){
                        dispacter.pause();
                        message.reply("Song paused! :pause_button:");
                    } else{
                        message.reply("Song is already paused");
                    }
                } else{
                    message.reply("No song is in the queue");
                }
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "next": {
        "usage": "",
        "description": "Skips to the next song in the queue",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                if(songQueue.length > 0){
                    dispacter.end();
                } else{
                    message.reply("There are no more songs :sob:");
                }
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "clear": {
        "usage": "",
        "description": "Clears the song queue",
        "process": function(message, args){
            if(message.member.voiceChannel !== undefined){
                if(songQueue.length === 0){
                    message.reply("There are no songs to clear");
                } else{
                    songQueue = [];
                    dispacter.end();
                    message.reply("The song queue has been cleared");
                }
            } else{
                message.reply("You can't hear my music if you're not in a voice channel :cry:");
            }
        }
    },
    "song": {
        "usage": "",
        "description": "Gives you information about the currently playing song",
        "process": function(message, args){
            if(songQueue.length > 0){
                message.reply(`The current song is \`${songQueue[0].title}\` :musical_note:, added by ${songQueue[0].user}`);
            } else{
                message.reply("No song is in the queue");
            }
        }
    },
    "music": {
        "usage": "",
        "description": "Gives you a list of the songs currently in the queue",
        "process": function(message, args){
            if(songQueue.length > 0){
                var songList = "";
                for(var i = 0; i < songQueue.length - 1; i++){
                    songList += `\`${songQueue[i].title}\`\n`;
                }
                songList += `\`${songQueue[songQueue.length - 1].title}\``;
                message.reply("The song queue currently has:\n" + songList);
            } else{
                message.reply("No song is in the queue");
            }
        }
    },
    "printsave": {
        "usage": "",
        "description": "Prints the save.json to the console for temporary saving",
        "process": function(message, args){
            fs.readFile("save.json", "utf8", function(err, data){
                if(err) throw err;
                console.log(JSON.parse(data));
                message.reply("The save file has been printed to the log");
            });
        }
    }
};

var addSong = function(message, url){
    ytdl.getInfo(url, function(err, info){
        if(err){
            message.reply("Sorry I couldn't get info for that song :cry:");
            return;
        }
        var song = {};
        song.title = info.title;
        song.url = url;
        song.user = message.author.username;
        songQueue.push(song);
        message.reply(`I have added \`${info.title}\` to the song queue! :headphones:`);
        if(songQueue.length === 1){
            message.member.voiceChannel.join().then(function(connection){playSong(message, connection)});
        }
    });
}

var playSong = function(message, connection){
    var stream = ytdl(songQueue[0].url, {"filter": "audioonly"});
    dispacter = connection.playStream(stream);
    message.channel.send(`Now playing \`${songQueue[0].title}\` :musical_note:, added by ${songQueue[0].user}`);
    dispacter.on("end", function(){
        songQueue.shift();
        if(songQueue.length === 0){
            message.channel.send("There are no more songs :sob:");
            message.member.voiceChannel.leave();
        } else{
            playSong(message, connection);
        }
    });
}

var checkForCommand = function(message){
    if(!message.author.bot && message.content.startsWith(prefix)){
        var args = message.content.substring(1).split(" ");
        var command = args.splice(0, 1);
        try{
            commands[command].process(message, args);
        } catch(e){
            message.reply("Sorry, that isn't a command yet :sob:");
            message.channel.send(`You can type \`${prefix}help\` to see a list of my commands`);
        }
    }
}

bot.on("ready", function(){console.log("Bot ready!")});
bot.on("disconnect", function(){
    console.log("Bot disconnected!");
    process.exit(1);
});
bot.on("guildMemberAdd", function(member){
    member.guild.defaultChannel.send(`Welcome to the server, ${member}! :smile:`);
    member.guild.defaultChannel.send(`You can type \`${prefix}help\` at anytime to see my commands`);
});
bot.on("message", function(message){checkForCommand(message)});
bot.on("messageUpdate", function(oldMessage, newMessage){checkForCommand(newMessage)});

bot.login(process.env.BOTTOKEN);

fs.readFile("save.json", function(err, data){
    if(err){
        if(err.code === "ENOENT"){
            console.log("save.json does not exist");
            fs.writeFile("save.json", "{}", "utf8", function(err){
                if(err) throw err
                console.log("save.json created");
            });
        } else{
            throw err;
        }
    }
});<|endoftext|>


<commit_before>
  defaults = {
      "chart": {
        chart: {
          type: 'spline'
        },
        "plotOptions": {
          "spline": {
            "marker": {
              "enabled": false
            }
          }
        },

        "tooltip": {
          "crosshairs": true
        }
      }
  }

  graphs = [

/*
    {
      chart: {
        chart: {
          type: 'column'
        },
        title: 'Example graph',
        yAxis: {
          title: {
            text: 'Essence'
          },
          min: -10,
          max: 50
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' EX'
        },
        plotOptions: {
          series: {
            marker: {
              symbol: 'diamond',
              enabled: 'true'
            }
          }
        }
      },
      select: {
        fields: ["field1", "field2"],
        mac: /18FE349B/
      }
    },
*/

    {
      chart: {
        chart: {
          type: 'line'
        },
        title: 'Uptime & Connections',
        yAxis: {
          title: {
            text: 'sec'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' sec'
        },
        plotOptions: {
          spline: {
            marker: {
              symbol: 'diamond',
              enabled: 'true'
            }
          }
        }
      },
      select: {
        fields: ["uptime"]
      }
    },

    {
      chart: {
        title: 'Free Memory',
        yAxis: {
          title: {
            text: 'bytes'
          }
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' bytes'
        }
      },
      select: {
        fields: ["freemem"]
      }
    },

    {
      chart: {
        title: 'Power Voltage',
        yAxis: {
          title: {
             text: 'mV'
          }
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' mV'
        }
      },
      select: {
        fields: ["vdd"]
      }
    },

    {
      chart: {
        title: 'Temperature',
        yAxis: {
          title: {
            text: '°C'
          },
          plotLines: [{
            value: 0,
            color: 'orange',
            dashStyle: 'shortdash',
            width: 1,
            label: {
              text: 'Null'
            }
          }],
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' °C'
        }
      },
      select: {
        fields: ["amt", "bmpt", "bmet", "dhtt1", "dhtt2", "ds", "dsw1", "dsw2", "dsw3", "dsw4", "dsw5", "dsw6", "dsw7", "dsw8", "dsw9", "dsw10", "dsw11", "dsw12", "dsw13", "dsw14", "dsw15"],
      }
    },

    {
      chart: {
        title: 'Humidity',
        yAxis: {
          title: {
             text: '%'
          },
          min: 0,
          plotLines: [{
            value: 20,
            color: 'green',
            dashStyle: 'shortdash',
            width: 1,
            label: {
              text: 'Critical low'
            }
          }, {
            value: 90,
            color: 'red',
            dashStyle: 'shortdash',
            width: 1,
            label: {
              text: 'Critical high'
            }
          }],
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' %'
        }
      },
      select: {
        fields: ["amh", "dhth1", "dhth2", "bmeh"]
      }
    },

    {
      chart: {
        title: 'Atmospheric pressure',
        yAxis: {
          title: {
             text: 'mmHg'
          }
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' mmHg'
        }
      },
      select: {
        fields: ["bmpp", "bmep"]
      }
    },

    {
      chart: {
        title: 'Brightness',
        yAxis: {
          title: {
             text: 'Lux'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' Lux'
        }
      },
      select: {
        fields: ["light"]
      }
    },

    {
      chart: {
        title: 'Analog-to-digital converter',
        yAxis: {
          title: {
             text: 'points'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' points'
        }
      },
      select: {
        fields: ["adc", "adc0", "adc1", "adc2", "adc3" ]
      }
    },

    {
      chart: {
        title: 'Pulse-Width Modulation status',
        yAxis: {
          title: {
             text: 'points'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' points'
        }
      },
      select: {
        fields: ["pwm0", "pwm1", "pwm2" ]
      }
    },

    {
      chart: {
        title: 'GPIO Input Monitor',
        yAxis: {
          title: {
             text: 'status'
          },
          min: 0,
          max: 1
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' status'
        }
      },
      select: {
        fields: ["gpioint", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio13", "gpiout13"]
      }
    },

    {
      chart: {
        title: 'Counter',
        yAxis: {
          title: {
             text: 'ps'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' ps'
        }
      },
      select: {
        fields: ["counter", "countrst"]
      }
    },

    {
      chart: {
        title: 'Counter v.2 (derivative)',
        yAxis: {
          title: {
             text: 'ps'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' ps'
        }
      },
      select: {
        fields: {counter: "DERIVATIVE(counter)"}
      }
    },

  ];

<commit_msg>Add nRF support<commit_after>
  defaults = {
      "chart": {
        chart: {
          type: 'spline'
        },
        "plotOptions": {
          "spline": {
            "marker": {
              "enabled": false
            }
          }
        },

        "tooltip": {
          "crosshairs": true
        }
      }
  }

  graphs = [

/*
    {
      chart: {
        chart: {
          type: 'column'
        },
        title: 'Example graph',
        yAxis: {
          title: {
            text: 'Essence'
          },
          min: -10,
          max: 50
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' EX'
        },
        plotOptions: {
          series: {
            marker: {
              symbol: 'diamond',
              enabled: 'true'
            }
          }
        }
      },
      select: {
        fields: ["field1", "field2"],
        mac: /18FE349B/
      }
    },
*/

    {
      chart: {
        chart: {
          type: 'line'
        },
        title: 'Uptime & Connections',
        yAxis: {
          title: {
            text: 'sec'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' sec'
        },
        plotOptions: {
          spline: {
            marker: {
              symbol: 'diamond',
              enabled: 'true'
            }
          }
        }
      },
      select: {
        fields: ["uptime"]
      }
    },

    {
      chart: {
        title: 'Free Memory',
        yAxis: {
          title: {
            text: 'bytes'
          }
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' bytes'
        }
      },
      select: {
        fields: ["freemem"]
      }
    },

    {
      chart: {
        title: 'Power Voltage',
        yAxis: {
          title: {
             text: 'mV'
          }
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' mV'
        }
      },
      select: {
        fields: ["vdd"]
      }
    },

    {
      chart: {
        title: 'Temperature',
        yAxis: {
          title: {
            text: '°C'
          },
          plotLines: [{
            value: 0,
            color: 'orange',
            dashStyle: 'shortdash',
            width: 1,
            label: {
              text: 'Null'
            }
          }],
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' °C'
        }
      },
      select: {
        fields: ["amt", "bmpt", "bmet", "dhtt1", "dhtt2", "ds", "dsw1", "dsw2", "dsw3", "dsw4", "dsw5", "dsw6", "dsw7", "dsw8", "dsw9", "dsw10", "dsw11", "dsw12", "dsw13", "dsw14", "dsw15", "nrf1t1"],
      }
    },

    {
      chart: {
        title: 'Humidity',
        yAxis: {
          title: {
             text: '%'
          },
          min: 0,
          plotLines: [{
            value: 20,
            color: 'green',
            dashStyle: 'shortdash',
            width: 1,
            label: {
              text: 'Critical low'
            }
          }, {
            value: 90,
            color: 'red',
            dashStyle: 'shortdash',
            width: 1,
            label: {
              text: 'Critical high'
            }
          }],
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' %'
        }
      },
      select: {
        fields: ["amh", "dhth1", "dhth2", "bmeh"]
      }
    },

    {
      chart: {
        title: 'Atmospheric pressure',
        yAxis: {
          title: {
             text: 'mmHg'
          }
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' mmHg'
        }
      },
      select: {
        fields: ["bmpp", "bmep"]
      }
    },

    {
      chart: {
        title: 'Brightness',
        yAxis: {
          title: {
             text: 'Lux'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' Lux'
        }
      },
      select: {
        fields: ["light"]
      }
    },

    {
      chart: {
        title: 'Analog-to-digital converter',
        yAxis: {
          title: {
             text: 'points'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' points'
        }
      },
      select: {
        fields: ["adc", "adc0", "adc1", "adc2", "adc3" ]
      }
    },

    {
      chart: {
        title: 'Pulse-Width Modulation status',
        yAxis: {
          title: {
             text: 'points'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' points'
        }
      },
      select: {
        fields: ["pwm0", "pwm1", "pwm2" ]
      }
    },

    {
      chart: {
        title: 'GPIO Input Monitor',
        yAxis: {
          title: {
             text: 'status'
          },
          min: 0,
          max: 1
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' status'
        }
      },
      select: {
        fields: ["gpioint", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio13", "gpiout13"]
      }
    },

    {
      chart: {
        title: 'Counter',
        yAxis: {
          title: {
             text: 'ps'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' ps'
        }
      },
      select: {
        fields: ["counter", "countrst", "nrf1c1"]
      }
    },

    {
      chart: {
        title: 'Counter v.2 (derivative)',
        yAxis: {
          title: {
             text: 'ps'
          },
          min: 0
        },
        tooltip: {
          crosshairs: true,
          valueSuffix: ' ps'
        }
      },
      select: {
        fields: {counter: "DERIVATIVE(counter)"}
      }
    },

  ];

<|endoftext|>


<commit_before>import marked from 'marked'
import moment from 'moment-timezone'

import {
  DEFAULT_LIMIT,
  DEFAULT_OFFSET,
  prepareAnimalResponse,
} from './base'

import db from '../database'
import pick from '../utils/pick'

import ConversationAnimal from '../models/conversationAnimal'
import Message from '../models/message'
import { addMessageActivity } from '../services/activity'
import { MessageBelongsToAnimal } from '../database/associations'

const permittedFields = [
  'text',
]

function prepareResponse(message, req) {
  const response = message.toJSON()
  const animalMe = req.meAnimal

  response.isWrittenByMe = (
    animalMe.userId === req.user.id &&
    animalMe.id === message.animal.id
  )

  const lastCheckedAt = animalMe.conversationsAnimals.updatedAt
  if (response.animal.id === animalMe.id) {
    response.isRead = true
  } else {
    response.isRead = moment(lastCheckedAt).isAfter(response.createdAt)
  }

  response.textHtml = marked(response.text)

  if (response.animal) {
    response.animal = prepareAnimalResponse(response.animal)
  }

  return response
}

function prepareResponseAll(rows, req) {
  return rows.map(row => prepareResponse(row, req))
}

export default {
  create: (req, res, next) => {
    const values = pick(permittedFields, req.body)

    return getConfig('isInboxEnabled').then(config => {
      if (!config.isInboxEnabled) {
        next(new APIError('Messaging is not available', httpStatus.FORBIDDEN))
        return null
      }

      // Create a message in that conversation
      return Message.create({
        animalId: req.meAnimal.id,
        conversationId: req.conversation.id,
        text: values.text,
      })
        .then(() => {
          return addMessageActivity({
            sendingAnimal: req.meAnimal,
            receivingAnimals: req.otherAnimals,
          })
        })
        .then(() => {
          res.json({ status: 'ok' })
        })
        .catch(err => next(err))
    })
  },
  findAll: (req, res, next) => {
    const {
      limit = DEFAULT_LIMIT,
      offset = DEFAULT_OFFSET,
    } = req.query

    return getConfig('isInboxEnabled').then(config => {
      if (!config.isInboxEnabled) {
        next(new APIError('Messaging is not available', httpStatus.FORBIDDEN))
        return null
      }

      // Find related conversation
      return Message.findAndCountAll({
        where: {
          conversationId: req.params.resourceId,
        },
        include: [
          MessageBelongsToAnimal,
        ],
        limit,
        offset,
        order: [
          ['createdAt', 'DESC'],
        ],
      })
        .then(result => {
          // Update last checked at date
          return ConversationAnimal.update({
            lastCheckedAt: db.fn('NOW'),
          }, {
            where: {
              animalId: req.meAnimal.id,
              conversationId: req.conversation.id,
            },
          })
            .then(() => {
              // Return messages
              res.json({
                data: prepareResponseAll(result.rows, req),
                limit: parseInt(limit, 10),
                offset: parseInt(offset, 10),
                total: result.count,
              })
            })
        })
        .catch(err => next(err))
    })
  },
}
<commit_msg>Add missing getConfig import<commit_after>import marked from 'marked'
import moment from 'moment-timezone'

import {
  DEFAULT_LIMIT,
  DEFAULT_OFFSET,
  prepareAnimalResponse,
} from './base'

import db from '../database'
import pick from '../utils/pick'

import ConversationAnimal from '../models/conversationAnimal'
import Message from '../models/message'
import { MessageBelongsToAnimal } from '../database/associations'
import { addMessageActivity } from '../services/activity'
import { getConfig } from '../config'

const permittedFields = [
  'text',
]

function prepareResponse(message, req) {
  const response = message.toJSON()
  const animalMe = req.meAnimal

  response.isWrittenByMe = (
    animalMe.userId === req.user.id &&
    animalMe.id === message.animal.id
  )

  const lastCheckedAt = animalMe.conversationsAnimals.updatedAt
  if (response.animal.id === animalMe.id) {
    response.isRead = true
  } else {
    response.isRead = moment(lastCheckedAt).isAfter(response.createdAt)
  }

  response.textHtml = marked(response.text)

  if (response.animal) {
    response.animal = prepareAnimalResponse(response.animal)
  }

  return response
}

function prepareResponseAll(rows, req) {
  return rows.map(row => prepareResponse(row, req))
}

export default {
  create: (req, res, next) => {
    const values = pick(permittedFields, req.body)

    return getConfig('isInboxEnabled').then(config => {
      if (!config.isInboxEnabled) {
        next(new APIError('Messaging is not available', httpStatus.FORBIDDEN))
        return null
      }

      // Create a message in that conversation
      return Message.create({
        animalId: req.meAnimal.id,
        conversationId: req.conversation.id,
        text: values.text,
      })
        .then(() => {
          return addMessageActivity({
            sendingAnimal: req.meAnimal,
            receivingAnimals: req.otherAnimals,
          })
        })
        .then(() => {
          res.json({ status: 'ok' })
        })
        .catch(err => next(err))
    })
  },
  findAll: (req, res, next) => {
    const {
      limit = DEFAULT_LIMIT,
      offset = DEFAULT_OFFSET,
    } = req.query

    return getConfig('isInboxEnabled').then(config => {
      if (!config.isInboxEnabled) {
        next(new APIError('Messaging is not available', httpStatus.FORBIDDEN))
        return null
      }

      // Find related conversation
      return Message.findAndCountAll({
        where: {
          conversationId: req.params.resourceId,
        },
        include: [
          MessageBelongsToAnimal,
        ],
        limit,
        offset,
        order: [
          ['createdAt', 'DESC'],
        ],
      })
        .then(result => {
          // Update last checked at date
          return ConversationAnimal.update({
            lastCheckedAt: db.fn('NOW'),
          }, {
            where: {
              animalId: req.meAnimal.id,
              conversationId: req.conversation.id,
            },
          })
            .then(() => {
              // Return messages
              res.json({
                data: prepareResponseAll(result.rows, req),
                limit: parseInt(limit, 10),
                offset: parseInt(offset, 10),
                total: result.count,
              })
            })
        })
        .catch(err => next(err))
    })
  },
}
<|endoftext|>


<commit_before>var utils = require('../config/utils');

var getInfo = function(req) {
  var userId = req.params.id;
  var models = req.app.get('models');
  var Review = models.Review;
  return {userId: userId, Review: Review};
};

var recursiveAdder = function(options, callback){
  var results = [];
  var invoker = function(index){
    if(options.reviews[index]){
      var review = options.reviews[index];
      review.authorId = options.utils.userId;

      options.utils.Review.sync().then(function() {
        return options.utils.Review.create(review);
      }).then(function(newReview) {
        results.push(newReview.dataValues);
        invoker(index+1);
      }).catch(function(err){
        console.log('Error: ', err);
      });

    }else{
      return callback(results);
    }
  };
  invoker(0);
};

module.exports = {

  getReviews: function(req, res){
    var reviewUtils = getInfo(req);

    reviewUtils.Review.sync().then(function() {
      return reviewUtils.Review.findAll({
        where: {subjectId: reviewUtils.userId}
      });
    })
    .then(function(results) {
      var totalStar = results.reduce(function(previous, current) {
        return previous + current.starRating;
      }, 0);
      var averageStar = totalStar / results.length;

      var reviews = results.map(function(data) {
        return {
          authorId: data.authorId,
          eventId: data.eventId,
          starRating: data.starRating,
          text: data.text,
          createdAt: data.createdAt
        };
      });

      var reviewData = {
        averageRating: averageStar,
        reviews: reviews
      };

      utils.sendResponse(res,200,reviewData);
    });
  },

  postReview: function(req, res){
    var reviewUtils = getInfo(req);
    var reviews = [];
    var count = 0;

    for(var i = 0; i < req.body.subjects.length; i++){
      reviews.push(req.body.subjects[i]);
    }

    var options = {
      count: count,
      reviews: reviews,
      utils: reviewUtils,
    };

    recursiveAdder(options, function(results){
      utils.sendResponse(res,200, results);
    });

  }
};
<commit_msg>removed unessesary code<commit_after>var utils = require('../config/utils');

var getInfo = function(req) {
  var userId = req.params.id;
  var models = req.app.get('models');
  var Review = models.Review;
  return {userId: userId, Review: Review};
};

var recursiveAdder = function(options, callback){
  var results = [];
  var invoker = function(index){
    if(options.reviews[index]){
      var review = options.reviews[index];
      review.authorId = options.utils.userId;

      options.utils.Review.sync().then(function() {
        return options.utils.Review.create(review);
      }).then(function(newReview) {
        results.push(newReview.dataValues);
        invoker(index+1);
      }).catch(function(err){
        console.log('Error: ', err);
      });

    }else{
      return callback(results);
    }
  };
  invoker(0);
};

module.exports = {

  getReviews: function(req, res){
    var reviewUtils = getInfo(req);

    reviewUtils.Review.sync().then(function() {
      return reviewUtils.Review.findAll({
        where: {subjectId: reviewUtils.userId}
      });
    })
    .then(function(results) {
      var totalStar = results.reduce(function(previous, current) {
        return previous + current.starRating;
      }, 0);
      var averageStar = totalStar / results.length;

      var reviews = results.map(function(data) {
        return {
          authorId: data.authorId,
          eventId: data.eventId,
          starRating: data.starRating,
          text: data.text,
          createdAt: data.createdAt
        };
      });

      var reviewData = {
        averageRating: averageStar,
        reviews: reviews
      };

      utils.sendResponse(res,200,reviewData);
    });
  },

  postReview: function(req, res){
    var reviewUtils = getInfo(req);
    var count = 0;

    var options = {
      count: count,
      reviews: req.body.subjects,
      utils: reviewUtils,
    };

    recursiveAdder(options, function(results){
      utils.sendResponse(res,200, results);
    });

  }
};
<|endoftext|>


<commit_before>var m = require('mithril');

var Movie = require('../model').Movie;
var buttonLabel = require('./widgets').buttonLabel;

function controller(main) {

  newTitle = m.prop("");
  flashMessages = m.prop([]);

  flash(status, msg) {
      flashMessages().push({ status: status, msg: msg });
  }

  function dismissFlash(index) {
    flashMessages().splice(index, 1);
    m.redraw();
  }

  function addMovie(e) {
    e.preventDefault();
    var title = newTitle().trim();
    if (title) {
      newTitle("");
      Movie.addNew(title).then(function(movie) {
        if (movie.Title) {
          flash("success", "\"" + movie.Title + "\" has been added to the list!");
          m.route("/movie/" + movie.imdbID);
        } else {
          flash("warning", "Sorry, no movie found with the title \"" + title + "\"");
        }
      });
    }
  }

  return function() {
    return {
      addMovie: addMovie,
      flashMessages: flashMessages,
      newTitle: newTitle,
      main: main,
      flash: flash,
      dismissAlert: dismissAlert
    };
  };

}

function view(ctrl) {

  function showFlashMessage(alert, index) {
    // get around window timeout event issues: has to be better way
    var dismissFlashMessage = ctrl.dismissFlashMessage.bind(ctrl, index);
    window.setTimeout(dismissFlashMessage, 6000);

    return m("div.alert.alert-dismissable.alert-" + alert.level, {role: "alert"}, [
        m("button.close[type=button][aria-label=Close][data-dismiss=alert]",  {
          onclick: dismissFlashMessage
        },
        m("span[aria-hidden=true]", m.trust("×"))),
        alert.msg
    ]);
  }

  return m("div.container", [
     m("h1", "Random movies"),
      ctrl.flashMessaages().map(showFlashMessage),
      m("form.form-horizontal", {onsubmit: ctrl.addMovie}, [
        m("div.form-group", m("input.form-control.form-control-bg", {
            type: "text",
            placeholder: "Add another title",
            value: ctrl.newTitle(),
            onchange: m.withAttr("value", ctrl.newTitle)
          })),
        m("div.form-group", m("button.form-control.btn.btn-primary[type=submit]", buttonLabel("plus", "Add")))
     ]),
     m.component(ctrl.main, {parent: ctrl})
  ]);
}

module.exports = function(main) {

  return {
      controller: controller(main),
      view: view
  };

};
<commit_msg>Typos<commit_after>var m = require('mithril');

var Movie = require('../model').Movie;
var buttonLabel = require('./widgets').buttonLabel;

function controller(main) {

  newTitle = m.prop("");
  flashMessages = m.prop([]);

  function flash(status, msg) {
      flashMessages().push({ status: status, msg: msg });
  }

  function dismissFlash(index) {
    flashMessages().splice(index, 1);
    m.redraw();
  }

  function addMovie(e) {
    e.preventDefault();
    var title = newTitle().trim();
    if (title) {
      newTitle("");
      Movie.addNew(title).then(function(movie) {
        if (movie.Title) {
          flash("success", "\"" + movie.Title + "\" has been added to the list!");
          m.route("/movie/" + movie.imdbID);
        } else {
          flash("warning", "Sorry, no movie found with the title \"" + title + "\"");
        }
      });
    }
  }

  return function() {
    return {
      addMovie: addMovie,
      flashMessages: flashMessages,
      newTitle: newTitle,
      main: main,
      flash: flash,
      dismissAlert: dismissAlert
    };
  };

}

function view(ctrl) {

  function showFlashMessage(alert, index) {
    // get around window timeout event issues: has to be better way
    var dismissFlashMessage = ctrl.dismissFlashMessage.bind(ctrl, index);
    window.setTimeout(dismissFlashMessage, 6000);

    return m("div.alert.alert-dismissable.alert-" + alert.level, {role: "alert"}, [
        m("button.close[type=button][aria-label=Close][data-dismiss=alert]",  {
          onclick: dismissFlashMessage
        },
        m("span[aria-hidden=true]", m.trust("×"))),
        alert.msg
    ]);
  }

  return m("div.container", [
     m("h1", "Random movies"),
      ctrl.flashMessages().map(showFlashMessage),
      m("form.form-horizontal", {onsubmit: ctrl.addMovie}, [
        m("div.form-group", m("input.form-control.form-control-bg", {
            type: "text",
            placeholder: "Add another title",
            value: ctrl.newTitle(),
            onchange: m.withAttr("value", ctrl.newTitle)
          })),
        m("div.form-group", m("button.form-control.btn.btn-primary[type=submit]", buttonLabel("plus", "Add")))
     ]),
     m.component(ctrl.main, {parent: ctrl})
  ]);
}

module.exports = function(main) {

  return {
      controller: controller(main),
      view: view
  };

};
<|endoftext|>


<commit_before>/*
 * This file is part of e-Giełda.
 * Copyright (C) 2014-2015  Mateusz Maćkowski and Tomasz Zieliński
 *
 * e-Giełda is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with e-Giełda.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * ISBN finder which retrieves information about the book when ISBN is entered.
 */

var egielda = egielda || {};

egielda.isbnFinder = function() {
    'use strict';

    var INVALID_ISBN = gettext('This ISBN is invalid.'),
        BOOK_NOT_FOUND =
            gettext('The book wasn\'t found. Please check the ISBN or fill out the form manually.');
    var get = egielda.jQ.get;

    function getInputByName(name) {
        return get('input[name="' + name + '"]');
    }

    var searchIsbnButton = get('<button class="ui icon button" disabled="disabled">' +
        '</button>');
    var isbnInput = getInputByName('isbn');

    // Ported from utils/isbn.py
    function isIsbnValid(isbn) {
        function isbnToDigitArray(isbn) {
            var arr = [];
            for (var i = 0; i < isbn.length; ++i) {
                arr.push(isbn[i] == 'X' ? 'X' : parseInt(isbn[i]));
            }
            return arr;
        }

        function calcIsbn10CheckDigit(isbn) {
            isbn = isbnToDigitArray(isbn);

            var tmp = 0;
            for (var i = 0; i < 9; ++i) {
                tmp += (i + 1) * isbn[i];
            }
            tmp %= 11;
            return tmp == 10 ? 'X' : tmp;
        }

        function calcIsbn13CheckDigit(isbn) {
            isbn = isbnToDigitArray(isbn);

            var tmp = 0;
            for (var i = 0; i < 12; i += 2) {
                tmp += isbn[i];
            }
            for (i = 1; i < 12; i += 2) {
                tmp += 3 * isbn[i];
            }
            return (10 - tmp % 10) % 10;
        }

        if (isbn.length == 10) {
            for (var i = 0; i < isbn.length - 1; ++i) {
                if (isbn[i] < '0' || isbn[i] > '9') {
                    return false;
                }
            }
            if (isbn[isbn.length - 1] != 'X' &&
                (isbn[isbn.length - 1] < '0' || isbn[isbn.length - 1] > '9')) {
                return false;
            }
            if (isbn[isbn.length - 1] != calcIsbn10CheckDigit(isbn)) {
                return false;
            }
        } else if (isbn.length == 13) {
            if (isbn[isbn.length - 1] != calcIsbn13CheckDigit(isbn)) {
                return false;
            }
        } else {
            return false;
        }
        return true;
    }

    function setSearchIsbnIcon(icon) {
        searchIsbnButton.children('i').removeClass().addClass('icon').addClass(icon);
    }

    function setSearchIsbnStatus(success, text, clearFields) {
        searchIsbnButton.removeClass('loading');

        if (success) {
            setSearchIsbnIcon('checkmark');
            searchIsbnButton.disable();
        } else {
            setSearchIsbnIcon('cancel');
            // 'is visible' returns either true or element, so we have to compare it to true
            if (searchIsbnButton.popup('is visible') !== true) {
                searchIsbnButton.popup({
                    content: text,
                    position: 'top right',
                    onHidden: function() {
                        searchIsbnButton.popup('destroy');
                    }
                });

                searchIsbnButton.popup('show');
            }

            if (clearFields) {
                $.each(['title', 'publication_year', 'publisher'], function() {
                    getInputByName(this).setText('');
                });
            }
        }
    }

    function clearSearchIsbnStatus() {
        setSearchIsbnIcon('search');
        searchIsbnButton.popup('hide');
    }

    searchIsbnButton.on('click', function(e) {
        e.preventDefault();

        // remove all chars which are not allowed
        var isbn = isbnInput.getText().toUpperCase().replace(/[^\dX]/g, '');
        if (!isIsbnValid(isbn)) {
            setSearchIsbnStatus(false, INVALID_ISBN, true);
            return;
        }

        searchIsbnButton.addClass('loading');
        var url = 'https://www.googleapis.com/books/v1/volumes?q=isbn:' + isbn +
            '&fields=items(selfLink)';
        $.ajax(url)
            .success(function(data) {
                var link;
                try {
                    link = data.items[0].selfLink;
                } catch (err) {
                    setSearchIsbnStatus(false, BOOK_NOT_FOUND, true);
                    return;
                }

                $.ajax(link + '?fields=volumeInfo(title,subtitle,publisher,publishedDate)')
                    .success(function(data) {
                        setSearchIsbnStatus(true);

                        var title = data.volumeInfo.title || '';
                        if (data.volumeInfo.subtitle != undefined) {
                            title += ': ' + data.volumeInfo.subtitle;
                        }
                        var publisher = data.volumeInfo.publisher || '';
                        var publicationYear = data.volumeInfo.publishedDate || '';

                        getInputByName('publisher').setText(publisher.substring(0, 150));
                        getInputByName('title').setText(title.substring(0, 250));
                        getInputByName('publication_year')
                            .setText(publicationYear.substring(0, 4));
                    })
                    .fail(function() {
                        setSearchIsbnStatus(false, BOOK_NOT_FOUND, true);
                    });
            })
            .fail(function() {
                setSearchIsbnStatus(false, BOOK_NOT_FOUND, true);
            });
    });

    function checkSearchAvailability() {
        var isbn = isbnInput.getText();
        isbn = isbn.toUpperCase().replace(/[^\dX]/g, ''); // remove all chars which are not allowed

        if (isbn.length != 10 && isbn.length != 13) {
            searchIsbnButton.disable();
        } else {
            searchIsbnButton.enable();
        }
    }

    // track user input to disable or enable search's button when applicable
    checkSearchAvailability.call(isbnInput);
    isbnInput.on('input', function() {
        clearSearchIsbnStatus();
        checkSearchAvailability();
    });

    // append controls to document
    isbnInput.wrap('
').parent().append(searchIsbnButton);

    // Add some util functions to egielda namespace
    egielda.isbnFinderUtils = {
        isIsbnValid: isIsbnValid,
        setSearchIsbnStatus: setSearchIsbnStatus
    };
};
<commit_msg>Add hide delay to isbnfinder popup<commit_after>/*
 * This file is part of e-Giełda.
 * Copyright (C) 2014-2015  Mateusz Maćkowski and Tomasz Zieliński
 *
 * e-Giełda is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with e-Giełda.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * ISBN finder which retrieves information about the book when ISBN is entered.
 */

var egielda = egielda || {};

egielda.isbnFinder = function() {
    'use strict';

    var INVALID_ISBN = gettext('This ISBN is invalid.'),
        BOOK_NOT_FOUND =
            gettext('The book wasn\'t found. Please check the ISBN or fill out the form manually.');
    var get = egielda.jQ.get;

    function getInputByName(name) {
        return get('input[name="' + name + '"]');
    }

    var searchIsbnButton = get('<button class="ui icon button" disabled="disabled">' +
        '</button>');
    var isbnInput = getInputByName('isbn');

    // Ported from utils/isbn.py
    function isIsbnValid(isbn) {
        function isbnToDigitArray(isbn) {
            var arr = [];
            for (var i = 0; i < isbn.length; ++i) {
                arr.push(isbn[i] == 'X' ? 'X' : parseInt(isbn[i]));
            }
            return arr;
        }

        function calcIsbn10CheckDigit(isbn) {
            isbn = isbnToDigitArray(isbn);

            var tmp = 0;
            for (var i = 0; i < 9; ++i) {
                tmp += (i + 1) * isbn[i];
            }
            tmp %= 11;
            return tmp == 10 ? 'X' : tmp;
        }

        function calcIsbn13CheckDigit(isbn) {
            isbn = isbnToDigitArray(isbn);

            var tmp = 0;
            for (var i = 0; i < 12; i += 2) {
                tmp += isbn[i];
            }
            for (i = 1; i < 12; i += 2) {
                tmp += 3 * isbn[i];
            }
            return (10 - tmp % 10) % 10;
        }

        if (isbn.length == 10) {
            for (var i = 0; i < isbn.length - 1; ++i) {
                if (isbn[i] < '0' || isbn[i] > '9') {
                    return false;
                }
            }
            if (isbn[isbn.length - 1] != 'X' &&
                (isbn[isbn.length - 1] < '0' || isbn[isbn.length - 1] > '9')) {
                return false;
            }
            if (isbn[isbn.length - 1] != calcIsbn10CheckDigit(isbn)) {
                return false;
            }
        } else if (isbn.length == 13) {
            if (isbn[isbn.length - 1] != calcIsbn13CheckDigit(isbn)) {
                return false;
            }
        } else {
            return false;
        }
        return true;
    }

    function setSearchIsbnIcon(icon) {
        searchIsbnButton.children('i').removeClass().addClass('icon').addClass(icon);
    }

    function setSearchIsbnStatus(success, text, clearFields) {
        searchIsbnButton.removeClass('loading');

        if (success) {
            setSearchIsbnIcon('checkmark');
            searchIsbnButton.disable();
        } else {
            setSearchIsbnIcon('cancel');
            // 'is visible' returns either true or element, so we have to compare it to true
            if (searchIsbnButton.popup('is visible') !== true) {
                searchIsbnButton.popup({
                    content: text,
                    position: 'top right',
                    delay: {
                        hide: 1500
                    },
                    onHidden: function() {
                        searchIsbnButton.popup('destroy');
                    }
                });

                searchIsbnButton.popup('show');
            }

            if (clearFields) {
                $.each(['title', 'publication_year', 'publisher'], function() {
                    getInputByName(this).setText('');
                });
            }
        }
    }

    function clearSearchIsbnStatus() {
        setSearchIsbnIcon('search');
        searchIsbnButton.popup('hide');
    }

    searchIsbnButton.on('click', function(e) {
        e.preventDefault();

        // remove all chars which are not allowed
        var isbn = isbnInput.getText().toUpperCase().replace(/[^\dX]/g, '');
        if (!isIsbnValid(isbn)) {
            setSearchIsbnStatus(false, INVALID_ISBN, true);
            return;
        }

        searchIsbnButton.addClass('loading');
        var url = 'https://www.googleapis.com/books/v1/volumes?q=isbn:' + isbn +
            '&fields=items(selfLink)';
        $.ajax(url)
            .success(function(data) {
                var link;
                try {
                    link = data.items[0].selfLink;
                } catch (err) {
                    setSearchIsbnStatus(false, BOOK_NOT_FOUND, true);
                    return;
                }

                $.ajax(link + '?fields=volumeInfo(title,subtitle,publisher,publishedDate)')
                    .success(function(data) {
                        setSearchIsbnStatus(true);

                        var title = data.volumeInfo.title || '';
                        if (data.volumeInfo.subtitle != undefined) {
                            title += ': ' + data.volumeInfo.subtitle;
                        }
                        var publisher = data.volumeInfo.publisher || '';
                        var publicationYear = data.volumeInfo.publishedDate || '';

                        getInputByName('publisher').setText(publisher.substring(0, 150));
                        getInputByName('title').setText(title.substring(0, 250));
                        getInputByName('publication_year')
                            .setText(publicationYear.substring(0, 4));
                    })
                    .fail(function() {
                        setSearchIsbnStatus(false, BOOK_NOT_FOUND, true);
                    });
            })
            .fail(function() {
                setSearchIsbnStatus(false, BOOK_NOT_FOUND, true);
            });
    });

    function checkSearchAvailability() {
        var isbn = isbnInput.getText();
        isbn = isbn.toUpperCase().replace(/[^\dX]/g, ''); // remove all chars which are not allowed

        if (isbn.length != 10 && isbn.length != 13) {
            searchIsbnButton.disable();
        } else {
            searchIsbnButton.enable();
        }
    }

    // track user input to disable or enable search's button when applicable
    checkSearchAvailability.call(isbnInput);
    isbnInput.on('input', function() {
        clearSearchIsbnStatus();
        checkSearchAvailability();
    });

    // append controls to document
    isbnInput.wrap('
').parent().append(searchIsbnButton);

    // Add some util functions to egielda namespace
    egielda.isbnFinderUtils = {
        isIsbnValid: isIsbnValid,
        setSearchIsbnStatus: setSearchIsbnStatus
    };
};
<|endoftext|>


<commit_before>/* eslint-disable prefer-arrow-callback */
angular.module('MyApp', ['ngResource', 'ngMessages', 'ngRoute', 'ngAnimate', 'mgcrea.ngStrap'])
	.config(function ($locationProvider, $routeProvider) {
		$locationProvider.html5Mode(true);

		$routeProvider
		.when('/', {
			templateUrl: 'views/home.html',
			controller: 'MainCtrl',
		})
		.when('/shows/:id', {
			templateUrl: 'views/detail.html',
			controller: 'DetailCtrl',
		})
		.when('/login', {
			templateUrl: 'views/login.html',
			controller: 'LoginCtrl',
		})
		.when('/signup', {
			templateUrl: 'views/signup.html',
			controller: 'SignupCtrl',
		})
		.when('/add', {
			templateUrl: 'views/add.html',
			controller: 'AddCtrl',
		})
		.otherwise({
			redirectTo: '/',
		});
	})
	.config(($httpProvider) => {
		$httpProvider.interceptors.push(($rootScope, $q, $window, $location) => ({
			request(config) {
				if ($window.localStorage.token) {
					config.headers.Authorization = `Bearer ${$window.localStorage.token}`;
				}
				return config;
			},
			responseError(response) {
				if (response.status === 401 || response.status === 403) {
					$location.path('/login');
				}
				return $q.reject(response);
			},
		}));
	})
	.run(($rootScope, $location) => {});		// eslint-disable-line no-unused-vars
/* eslint-enable prefer-arrow-callback */
<commit_msg>removed #run() from the app.js<commit_after>/* eslint-disable prefer-arrow-callback */
angular.module('MyApp', ['ngResource', 'ngMessages', 'ngRoute', 'ngAnimate', 'mgcrea.ngStrap'])
	.config(function ($locationProvider, $routeProvider) {
		$locationProvider.html5Mode(true);

		$routeProvider
		.when('/', {
			templateUrl: 'views/home.html',
			controller: 'MainCtrl',
		})
		.when('/shows/:id', {
			templateUrl: 'views/detail.html',
			controller: 'DetailCtrl',
		})
		.when('/login', {
			templateUrl: 'views/login.html',
			controller: 'LoginCtrl',
		})
		.when('/signup', {
			templateUrl: 'views/signup.html',
			controller: 'SignupCtrl',
		})
		.when('/add', {
			templateUrl: 'views/add.html',
			controller: 'AddCtrl',
		})
		.otherwise({
			redirectTo: '/',
		});
	})
	.config(($httpProvider) => {
		$httpProvider.interceptors.push(($rootScope, $q, $window, $location) => ({
			request(config) {
				if ($window.localStorage.token) {
					config.headers.Authorization = `Bearer ${$window.localStorage.token}`;
				}
				return config;
			},
			responseError(response) {
				if (response.status === 401 || response.status === 403) {
					$location.path('/login');
				}
				return $q.reject(response);
			},
		}));
	});
/* eslint-enable prefer-arrow-callback */
<|endoftext|>


<commit_before>const electron = require('electron')
const remote = electron.remote
const Promise = require('bluebird')
const config = remote.require('./lib/config')
require('coffee-script/register')

// webview focus area fix
// This is a workaround for https://bugs.chromium.org/p/chromium/issues/detail?id=600395
window.onclick = (e) => {
  remote.getCurrentWindow().webContents.executeJavaScript(`
    $('webview').blur()
    $('webview').focus()
  `)
}

// Faster align setting
const webFrame = electron.webFrame

const alertCSS =
`#alert {
  transform: scale(0.8);
  left: 80px !important;
  top: -80px !important;
}
`

const alignCSS = document.createElement('style')

const getWebviewWidth = Promise.coroutine(function* () {
  const width = yield new Promise((resolve, reject) => {
    remote.getCurrentWindow().webContents.executeJavaScript("$('webview').getBoundingClientRect().width", (result) => {
      resolve(result)
    })
  })
  return width
})

window.align = Promise.coroutine(function* () {
  let zoom = yield getWebviewWidth()
  zoom = zoom / 800
  webFrame.setZoomFactor(zoom)
  window.scrollTo(0, 0)
  if (!window.location.toString().includes("http://www.dmm.com/netgame/social/-/gadgets/=/app_id=854854/")) {
    return
  }
  alignCSS.innerHTML =
  `html {
    overflow: hidden;
  }
  #w, #main-ntg {
    position: absolute !important;
    top: 0;
    left: 0;
    z-index: 100;
    margin-left: 0 !important;
    margin-top: 0 !important;
  }
  #game_frame {
    width: 800px !important;
    position: absolute;
    top: -16px;
    left: 0;
  }
  #spacing_top {
    display: none;
  }
  .naviapp {
    z-index: -1;
  }
  #ntg-recommend {
    display: none !important;
  }
  `
})

window.unalign = () => {
  alignCSS.innerHTML = ""
}

window.align()

remote.getCurrentWebContents().insertCSS(alertCSS)
document.addEventListener("DOMContentLoaded", (e) => {
  window.align()
  document.querySelector('body').appendChild(alignCSS)
  const flashQuality = config.get('poi.flashQuality', 'high')
  const setQuality = () => {
    const iframeDoc = document.querySelector('#game_frame') ? document.querySelector('#game_frame').contentWindow.document : document
    const flash = iframeDoc.querySelector('#externalswf').cloneNode(true)
    flash.setAttribute('quality', flashQuality)
    iframeDoc.querySelector('#externalswf').remove()
    iframeDoc.querySelector('#flashWrap').appendChild(flash)
  }
  const t = setInterval(() => {
    try {
      setQuality()
      console.warn('Successed.', new Date())
      clearInterval(t)
    } catch (e) {
      console.warn('Failed. Will retry in 100ms.')
    }
  }, 100)
})
<commit_msg>Better align<commit_after>const electron = require('electron')
const remote = electron.remote
const Promise = require('bluebird')
const config = remote.require('./lib/config')
require('coffee-script/register')

// webview focus area fix
// This is a workaround for https://bugs.chromium.org/p/chromium/issues/detail?id=600395
window.onclick = (e) => {
  remote.getCurrentWindow().webContents.executeJavaScript(`
    $('webview').blur()
    $('webview').focus()
  `)
}

// Faster align setting
const webFrame = electron.webFrame

const alertCSS =
`#alert {
  transform: scale(0.8);
  left: 80px !important;
  top: -80px !important;
}
`

const alignCSS = document.createElement('style')
const alignInnerCSS = document.createElement('style')

const getWebviewWidth = Promise.coroutine(function* () {
  const width = yield new Promise((resolve, reject) => {
    remote.getCurrentWindow().webContents.executeJavaScript("$('webview').getBoundingClientRect().width", (result) => {
      resolve(result)
    })
  })
  return width
})

window.align = Promise.coroutine(function* () {
  let zoom = yield getWebviewWidth()
  zoom = zoom / 800
  webFrame.setZoomFactor(zoom)
  window.scrollTo(0, 0)
  if (!window.location.toString().includes("http://www.dmm.com/netgame/social/-/gadgets/=/app_id=854854/")) {
    return
  }
  alignCSS.innerHTML =
  `html {
    overflow: hidden;
  }
  #w, #main-ntg {
    position: absolute !important;
    top: 0;
    left: 0;
    z-index: 100;
    margin-left: 0 !important;
    margin-top: 0 !important;
  }
  #game_frame {
    width: 800px !important;
    position: absolute;
    top: 0px;
    left: 0;
  }
  .naviapp {
    z-index: -1;
  }
  #ntg-recommend {
    display: none !important;
  }
  `
  alignInnerCSS.innerHTML = `
  #spacing_top {
    display: none;
  }
  `
})

window.unalign = () => {
  alignCSS.innerHTML = ""
}

window.align()

remote.getCurrentWebContents().insertCSS(alertCSS)
document.addEventListener("DOMContentLoaded", (e) => {
  window.align()
  document.querySelector('body').appendChild(alignCSS)
  const flashQuality = config.get('poi.flashQuality', 'high')
  const t = setInterval(() => {
    try {
      const iframeDoc = document.querySelector('#game_frame') ? document.querySelector('#game_frame').contentWindow.document : document
      iframeDoc.querySelector('body').appendChild(alignInnerCSS)
      const flash = iframeDoc.querySelector('#externalswf').cloneNode(true)
      flash.setAttribute('quality', flashQuality)
      iframeDoc.querySelector('#externalswf').remove()
      iframeDoc.querySelector('#flashWrap').appendChild(flash)
      console.warn('Successed.', new Date())
      clearInterval(t)
    } catch (e) {
      console.warn('Failed. Will retry in 100ms.')
    }
  }, 100)
})
<|endoftext|>


<commit_before>/**
 * Copyright 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule ReactPropTypesSecret
 */

'use strict';

const ReactPropTypesSecret = '__REACT_PROP_TYPES_SECRET__' + Math.random().toString();

module.exports = ReactPropTypesSecret;
<commit_msg>Use hardcoded value for PropType secret (#7194)<commit_after>/**
 * Copyright 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule ReactPropTypesSecret
 */

'use strict';

const ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';

module.exports = ReactPropTypesSecret;
<|endoftext|>


<commit_before>
// This file will manage waypoint data

var pd = {};
module.exports = pd;

// this will add the list of items to the properties
pd.warmUp = function() {

}

// This function will check the data to see if it's been inited.
pd.checkStatus = function() {
	// if not inited, call warm up
}

// This will add a waypoint
pd.add =function (waypoint) {

}

// This will remove a waypoint
pd.remove = function (waypoint) {

}

<commit_msg>Added more detail in the comments<commit_after>
// This file will manage waypoint data if I can get to the "add waypoint" feature
var pd = {};
module.exports = pd;

// this will add the list of default waypoints to the properties when the app is first launched
// maybe I should just keep the default waypoints hardcoded, and make this do that
pd.warmUp = function() {

}

// This function will check the data to see if there are any user-created waypoints. If so, add them to the waypoint tableview, but in another section (group)
pd.checkStatus = function() {
	// if not inited, call warm up
}

// This will add a user waypoint
pd.add =function (waypoint) {

}

// This will remove a user waypoint
pd.remove = function (waypoint) {

}

<|endoftext|>