diff --git a/lib/BetterDiscord.devp.js b/lib/BetterDiscord.devp.js index fe913f5..37c5680 100644 --- a/lib/BetterDiscord.devp.js +++ b/lib/BetterDiscord.devp.js @@ -16,7 +16,6 @@ var _extData = {}; function BetterDiscord(mainWindow) { - console.log("WTHFHUFHEIUWHFEUIHFWIUHFEIU"); _mainWindow = mainWindow; _cfg = _config.cfg; @@ -30,7 +29,7 @@ function BetterDiscord(mainWindow) { function createAndCheckData() { getUtils().log("Checking data/cache"); - _cfg.dataPath = (_cfg.os == 'win32' ? process.env.APPDATA : _cfg.os == 'darwin' ? process.env.HOME + '/Library/Preferences' : '/var/local') + '/BetterDiscordTest/'; + _cfg.dataPath = (_cfg.os == 'win32' ? process.env.APPDATA : _cfg.os == 'darwin' ? process.env.HOME + '/Library/Preferences' : '/var/local') + '/BetterDiscordDev/'; _cfg.userFile = _cfg.dataPath + 'user.json'; try { @@ -73,6 +72,7 @@ function init() { if(_cfg.branch == null) { _cfg.branch = _cfg.beta ? "beta" : "master"; } + getUtils().log("Using repo: " + _cfg.repo + " with branch: " + _cfg.branch); getUtils().download("api.github.com", "/repos/" + _cfg.repo + "/BetterDiscordApp/commits/" + _cfg.branch, function(data) { @@ -103,6 +103,7 @@ function initUpdater() { try { _cfg.updater = JSON.parse(data); } catch(err) { + getUtils().err(err); exit("Failed to load updater"); return; } @@ -128,9 +129,9 @@ function updateExtData() { getUtils().log("Updating ext data"); _extData = { - 'load-jQueryUI': { + 'load-jQueryCookie': { 'type': 'javascript', - 'resource': 'jQueryUI', + 'resource': 'jQueryCookie', 'domain': 'cdnjs.cloudflare.com', 'url': '//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js', 'localurl': null, @@ -154,7 +155,7 @@ function updateExtData() { 'domain': _cfg.updater.CDN, 'url': '//' + _cfg.updater.CDN + '/' + _cfg.repo + '/BetterDiscordApp/' + _cfg.hash + '/js/main.min.js', 'localurl': _cfg.localServer + '/BetterDiscordApp/js/main.js', - 'message': 'load-publicServers', + 'message': 'load-emoteData-twitchGlobal', 'cacheable': false, 'variable': null }, @@ -328,6 +329,16 @@ function domReady() { function load(reload) { getUtils().log(reload ? "Reloading" : "Loading"); + + if(!reload) { + if(_cfg.updater.LatestVersion > _cfg.version) { + getUtils().alert("Update Available", "An update for BetterDiscord is available("+_cfg.updater.LatestVersion+")! BetterDiscord.net"); + } + getUtils().log("Hooking ipc async"); + getUtils().execJs("var betterDiscordIPC = require('electron').ipcRenderer;"); + _bdIpc.on('asynchronous-message', function(event, arg) { ipcAsyncMessage(event, arg); }); + getUtils().log("Hooked ipc async"); + } initLoaders(); } @@ -340,7 +351,7 @@ function initLoaders() { loadPlugins(); loadThemes(); - + loadApp(); }catch(err) { exit(err); } @@ -357,7 +368,7 @@ function loadPlugins() { var pluginErrors = []; - getUtils().injectVar("bdplugins", "{}"); + getUtils().injectVarRaw("bdplugins", "{}"); files.forEach(function(fileName) { if(!fileName.endsWith(".plugin.js")) { @@ -373,6 +384,25 @@ function loadPlugins() { pluginErrors.push(fileName + " Reason: Plugin META not found"); return; } + var pluginVar = meta.substring(meta.lastIndexOf('//META') + 6, meta.lastIndexOf('*//')); + var parse; + try { + parse = JSON.parse(pluginVar); + }catch(err) { + getUtils().warn("Failed to parse plugin META in file: " + fileName + "("+err+")"); + pluginErrors.push(fileName + " Reason: Failed to parse plugin META (" + err + ")"); + return; + } + + if(parse["name"] == undefined) { + getUtils().warn("Undefined plugin name in file: " + fileName); + pluginErrors.push(fileName + " Reason: invalid plugin name"); + return; + } + + getUtils().log("Loading plugin: " + parse["name"]); + getUtils().execJs(plugin); + getUtils().execJs('(function() { var plugin = new ' + parse["name"] + '(); bdplugins[plugin.getName()] = { "plugin": plugin, "enabled": false } })();') }); if(pluginErrors.length > 0) { @@ -393,7 +423,7 @@ function loadThemes() { var themeErrors = []; - getUtils().injectVar("bdthtmes", "{}"); + getUtils().injectVarRaw("bdthemes", "{}"); files.forEach(function(fileName) { if(!fileName.endsWith(".theme.css")) { @@ -413,7 +443,7 @@ function loadThemes() { try { themeInfo = JSON.parse(themeVar); }catch(err) { - getUtils().warn("Failed to parse theme META in file ("+err+"): " + fileName); + getUtils().warn("Failed to parse theme META in file: " + fileName + "("+err+")"); themeErrors.push(fileName + " Reason: Failed to parse theme META (" + err + ")"); return; } @@ -435,9 +465,10 @@ function loadThemes() { getUtils().log("Loading theme: " + themeInfo['name']); split.splice(0, 1); - theme = split.join('\n'); + theme = split.join(_eol); theme = theme.replace(/(\r\n|\n|\r)/gm, ''); + _mainWindow.webContents.executeJavaScript('(function() { bdthemes["' + themeInfo['name'] + '"] = { "enabled": false, "name": "' + themeInfo['name'] + '", "css": "' + escape(theme) + '", "description": "' + themeInfo['description'] + '", "author":"' + themeInfo['author'] + '", "version":"' + themeInfo['version'] + '" } })();'); }); if(themeErrors.length > 0) { @@ -446,6 +477,214 @@ function loadThemes() { }); } +function loadApp() { + getUtils().execJs('var loadingNode = document.createElement("DIV");'); + getUtils().execJs('loadingNode.innerHTML = \'
BetterDiscord - Loading Libraries :
\''); + getUtils().execJs('var flex = document.getElementsByClassName("flex-vertical flex-spacer")[0]; flex.appendChild(loadingNode);'); + getUtils().injectVar('bdVersion', _cfg.version); + getUtils().injectVar('bdCdn', _cfg.CDN); + + getUtils().updateLoading("Loading Resource (jQuery)", 0, 100); + getUtils().injectJavaScriptSync("//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js", "load-jQueryCookie"); +} + +function ipcAsyncMessage(event, arg) { + + if(_extData.hasOwnProperty(arg)) { + loadExtData(_extData[arg]); + } + + if(arg == "start-bd") { + getUtils().updateLoading("Starting Up", 100, 100); + getUtils().execJs('var mainCore; var startBda = function() { mainCore = new Core(); mainCore.init(); }; startBda();'); + + //Remove loading node + setTimeout(function() { + getUtils().execJs('$("#bd-status").parent().parent().hide();'); + }, 2000); + getUtils().saveLogs(_cfg.dataPath); + } +} + +var loadCounter = 0; +function loadExtData(extData) { + + loadCounter++; + + getUtils().updateLoading("Loading Resource (" + extData.resource + ")", loadCounter / Object.keys(_extData).length * 100, 100); + + var url = (_cfg.local && extData.localurl != null) ? extData.localurl : extData.url; + + try { + switch(extData.type) { + case 'javascript': + getUtils().injectJavaScriptSync(url, extData.message); + break; + case 'css': + getUtils().injectStylesheetSync(url, extData.message); + break; + case 'json': + getUtils().download(extData.domain, extData.url, function(data) { + getUtils().injectVar(extData.variable, data); + getUtils().sendIcpAsync(extData.message); + }); + break; + case 'emotedata': + if(extData.variable != "emotesTwitch") { + getUtils().injectVarRaw(extData.variable, "{}"); + } + var exists = _fs.existsSync(extData.localpath); + if(exists && !_cfg.cache.expired && extData.cacheable) { + loadEmoteData(extData, true); + } else { + loadEmoteData(extData, false); + } + break; + } + }catch(err) { + getUtils().warn(err); + getUtils().alert("Something went wrong :( Attempting to run.", err); + getUtils().sendIcpAsync(extData.message); + } +} + +function loadEmoteData(extData, local) { + if(local) { + getUtils().log("Reading " + extData.resource + " from file"); + var data = _fs.readFileSync(extData.localpath, extData.encoding); + + if(testJSON(extData, data)) { + injectEmoteData(extData, data); + } else { + getUtils().log("Deleting cached file " + extData.resource); + _fs.unlinkSync(extData.localpath); + getUtils().sendIcpAsync(extData.self); + } + return; + } + + if(extData.https) { + getUtils().download(extData.domain, extData.url, function(data) { + var parsedEmoteData = parseEmoteData(extData, data); + if(parsedEmoteData == null) { + getUtils().sendIcpAsync(extData.fallback); + return true; + } + saveEmoteData(extData, parsedEmoteData); + injectEmoteData(extData, parsedEmoteData); + }); + return; + } + + getUtils().downloadHttp(extData.url, function(data) { + var parsedEmoteData = parseEmoteData(extData, data); + if(parsedEmoteData == null) { + getUtils().sendIcpAsync(extData.fallback); + return true; + } + saveEmoteData(extData, parsedEmoteData); + injectEmoteData(extData, parsedEmoteData); + }); + +} + +function testJSON(extData, data) { + getUtils().log("Validating " + extData.resource); + try { + var json = JSON.parse(data); + getUtils().log(extData.resource + " is valid"); + return true; + }catch(err) { + getUtils().warn(extData.resource + " is invalid"); + return false; + } + return false; +} + +function injectEmoteData(extData, data) { + if(data == null) { + getUtils().sendIcpAsync(extData.message); + return; + } + + if(data.parse) { + getUtils().injectVarRaw(extData.variable, 'JSON.parse(\'' + data + '\');'); + } else { + getUtils().injectVarRaw(extData.variable, data); + } + + getUtils().sendIcpAsync(extData.message); +} + +function saveEmoteData(extData, data) { + try { + getUtils().log("Saving resource to file " + extData.resource); + _fs.writeFileSync(extData.localpath, data, extData.encoding); + } catch(err) { + getUtils().err("Failed to save resource to file " + extData.resource); + } +} + +function parseEmoteData(extData, data) { + getUtils().log("Parsing: " + extData.resource); + + var returnData; + + switch(extData.specialparser) { + + case 0: //Twitch Global Emotes + //returnData = emoteData.replace(/\$/g, "\\$").replace(/'/g, "\\'").replace(/"/g, "\\\""); We don't need this anymore + return data; + break; + case 1: //Twitch Subscriber Emotes + returnData = {}; + if(!testJSON(extData, data)) { + return null; + } + + data = JSON.parse(data); + + var channels = data["channels"]; + for(var channel in channels) { + var emotes = channels[channel]["emotes"]; + for(var i = 0 ; i < emotes.length ; i++) { + var code = emotes[i]["code"]; + var id = emotes[i]["image_id"]; + returnData[code] = id; + } + } + + returnData = JSON.stringify(returnData); + break; + case 2: //FFZ Emotes + returnData = data; + break; + case 3: //BTTV Emotes + returnData = {}; + + if(!testJSON(extData, data)) { + return null; + } + + data = JSON.parse(data); + + for(var emote in data.emotes) { + emote = data.emotes[emote]; + var url = emote.url; + var code = emote.regex; + + returnData[code] = url; + } + + returnData = JSON.stringify(returnData); + break; + case 4: + returnData = data; + break; + } + return returnData; +} + function getUtils() { return _utils2; }