├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ └── issue-template.md ├── .gitignore ├── Firefox ├── @betterdiscord-0.0.1.xpi ├── README.md ├── betterdiscord-0.0.3-fx.xpi ├── data │ ├── css │ │ └── main.css │ └── js │ │ └── main.js ├── icon.png ├── lib │ ├── BdPageMod.js │ ├── BetterDiscord.js │ └── main.js ├── package.json └── test │ └── test-index.js ├── Gruntfile.js ├── ISSUE_TEMPLATE.md ├── Installers ├── Electron │ ├── .gitignore │ ├── package.json │ └── src │ │ ├── asar.js │ │ ├── data │ │ ├── css │ │ │ └── main.css │ │ ├── error.html │ │ ├── font │ │ │ ├── Inconsolata.woff2 │ │ │ └── OpenSans-Regular.ttf │ │ ├── index.html │ │ ├── js │ │ │ ├── jquery-2.0.0.min.js │ │ │ ├── jquery-2.2.2.min.js │ │ │ ├── main.js │ │ │ └── splash.js │ │ ├── splash.html │ │ └── vi.json │ │ ├── index.js │ │ ├── installer_index.js │ │ ├── package.json │ │ ├── updater.js │ │ └── utils.js ├── Node │ ├── config.json │ ├── index.js │ ├── install.bat │ └── install.sh ├── dotNet │ ├── .gitattributes │ ├── .gitignore │ ├── BetterDiscordWI.sln │ ├── BetterDiscordWI │ │ ├── App.config │ │ ├── App.manifest │ │ ├── BetterDiscord-icon.ico │ │ ├── BetterDiscordWI.csproj │ │ ├── FormMain.Designer.cs │ │ ├── FormMain.cs │ │ ├── FormMain.resx │ │ ├── Program.cs │ │ ├── Properties │ │ │ ├── AssemblyInfo.cs │ │ │ ├── Resources.Designer.cs │ │ │ ├── Resources.resx │ │ │ ├── Settings.Designer.cs │ │ │ └── Settings.settings │ │ ├── Resources │ │ │ ├── BetterDiscord-icon.ico │ │ │ ├── bd_logo2.png │ │ │ ├── bd_logo_64x64.png │ │ │ ├── bd_logo_64x64_nobg.png │ │ │ └── bd_logo_large_nobg.png │ │ ├── Utils.cs │ │ ├── components │ │ │ └── CTextBox.cs │ │ ├── packages.config │ │ └── panels │ │ │ ├── IPanel.cs │ │ │ ├── Panel0.Designer.cs │ │ │ ├── Panel0.cs │ │ │ ├── Panel0.resx │ │ │ ├── Panel1.Designer.cs │ │ │ ├── Panel1.cs │ │ │ ├── Panel1.resx │ │ │ ├── Panel2.Designer.cs │ │ │ ├── Panel2.cs │ │ │ ├── Panel2.resx │ │ │ ├── Panel3.Designer.cs │ │ │ └── Panel3.cs │ ├── README.md │ └── config.xml └── dotNet2 │ ├── BetterDiscordWI.sln │ └── BetterDiscordWI │ ├── App.config │ ├── BetterDiscordWI.csproj │ ├── FodyWeavers.xml │ ├── FormMain.Designer.cs │ ├── FormMain.cs │ ├── FormMain.resx │ ├── Program.cs │ ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings │ ├── Resources │ ├── Betterdiscord small black+blue.png │ └── Betterdiscord small white+blue.png │ ├── Utils.cs │ ├── app.manifest │ ├── betterdiscord_small_white_blue_icO_icon.ico │ ├── controls │ ├── Button.Designer.cs │ └── Button.cs │ ├── packages.config │ └── panels │ ├── ConfigPanel.Designer.cs │ ├── ConfigPanel.cs │ ├── ConfigPanel.resx │ ├── IPanel.cs │ ├── InstallPanel.Designer.cs │ ├── InstallPanel.cs │ ├── InstallPanel.resx │ ├── LicensePanel.Designer.cs │ ├── LicensePanel.cs │ └── LicensePanel.resx ├── LICENSE ├── Plugins ├── AutoPlayGifs.plugin.js ├── CustomGame.plugin.js ├── GuildsScroller.plugin.js ├── clock.plugin.js ├── customRoleColour.plugin.js ├── dblClickEdit.plugin.js ├── emoteBlacklist.plugin.js ├── mediaSupport.plugin.js ├── properTimestamps.plugin.js ├── typingsound.plugin.js └── videoSupport.js ├── README.md ├── betterdiscord.js ├── css ├── main.css └── main.min.css ├── data ├── emotedata_bttv.json ├── emotedata_ffz.json ├── emotedata_twitch.json ├── emotedata_twitch_global.json ├── emotedata_twitch_subscriber.json ├── emotefilter.json ├── serverlist.json ├── serverlist_archive.json └── updater.json ├── dev ├── css │ ├── CodeMirror.css │ ├── main.css │ ├── main.css.map │ └── main.sass └── js │ ├── 00settings.js │ ├── 01core.js │ ├── 02emoteModule.js │ ├── 03publicServers.js │ ├── 04quickEmoteMenu.js │ ├── 05customCssEditor.js │ ├── 06settingsPanel.js │ ├── 07utils.js │ ├── 08voiceMode.js │ ├── 09pluginModule.js │ ├── 10themeModule.js │ ├── 11webSocket.js │ └── 12api.js ├── html ├── pstest.html └── test.html ├── issues ├── js ├── main.js └── main.min.js ├── lib ├── BetterDiscord.devp.js ├── BetterDiscord.js ├── Utils.js └── config.json ├── misc ├── uninstall.bat ├── uninstall.js └── validator.js ├── package.json ├── splice └── v2 ├── .babelrc ├── Gruntfile.js ├── README.MD ├── dist └── js │ └── main.js ├── lib ├── config.json ├── core.js ├── main.js ├── test.js └── utils.js ├── package.json └── src └── js ├── api.js ├── core.js ├── event.js ├── modules ├── modules.js └── observermodule.js ├── plugin.js └── utils.js /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sh text=auto -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Issue template 3 | about: Template for all future issues 4 | 5 | --- 6 | 7 | *Before* you create an issue, make sure you have: 8 | 9 | 1. Checked that that issue hasn't already been submitted. You can search open issues [here](https://github.com/Jiiks/BetterDiscordApp/issues). 10 | 2. Checked that there isn't an answer in either of the Discord servers (if you can access them - don't complain if you can't). 11 | 3. Checked that it isn't in the following list of frequently asked questions. 12 | 13 | If none of that helps you, delete the prefilled contents of this issue and ask whatever question you may have *in English so we can understand it*. 14 | 15 | ### FAQ 16 | 17 | > *BetterDiscord doesn't work.* 18 | > *BetterDiscord won't install.* 19 | > *BetterDiscord doesn't support macOS.* 20 | 21 | This branch isn't being updated anymore. Until BetterDiscord v2 is released you can use [Zach Rauen's fork](https://github.com/rauenzi/BetterDiscordApp). 22 | 23 | > *BetterDiscord doesn't support Linux.* 24 | 25 | There's an installer script for BetterDiscord on Linux available [here](https://github.com/bb010g/betterdiscordctl). 26 | 27 | > *BetterDiscord doesn't work in my browser.* 28 | 29 | The browser version doesn't exist anymore. Use the desktop client. 30 | 31 | > *BetterDiscord doesn't work on my phone.* 32 | 33 | ... and never will. BetterDiscord is a client modification for Discord's desktop Electron client. (Electron is a framework for making cross platform apps using web technologies. Basically the desktop client is just the web client in a specialised web browser.) 34 | 35 | > *Is there any security risks involved with installing BetterDiscord?* 36 | > *My friend was hacked after he/she installed BetterDiscord.* 37 | 38 | *Not by itself.* However, BetterDiscord allows loading plugins. Discord, BetterDiscord, and any plugins you install (even without enabling) have full access to your system as your local user account. (Including full access to your Discord account.) So, make sure you only download plugins from sources you trust. 39 | 40 | Also, please note that [BetterDocs](https://betterdocs.net) and other third-party sources by definition *are not* affiliated with BetterDiscord or it's developers. 41 | 42 | > *How do I install plugin [x]?* 43 | > *Is there a plugin to [x]?* 44 | > *Does [x] theme exist?* 45 | 46 | https://imgur.com/lczPQxW 47 | 48 | > *Minimal mode broke everything.* 49 | 50 | You can get back into Discord's settings to disable it by pressing `Control + ,` on Windows and Linux or `Command + ,` on macOS. 51 | 52 | > *How do I completely hide messages from people I've blocked?* 53 | 54 | Add this to your custom CSS: 55 | 56 | ```css 57 | .message-group-blocked { 58 | display: none !important; 59 | } 60 | ``` 61 | 62 | > *How do I remove BetterDiscord?* 63 | 64 | BetterDiscord is installed to the following locations: 65 | 66 | Platform | Discord path 67 | -------------|--------------- 68 | Windows | `%APPDATA%`\discord\0.0.`*`\modules\discord_desktop_core 69 | macOS | ~/Library/Application Support/discord/0.0.`*`/modules/discord_desktop_core 70 | Linux | ~/.config/discord/0.0.`*`/modules/discord_desktop_core 71 | 72 | To remove BetterDiscord, open the file `index.js` in that directory and make sure only this line exists: 73 | 74 | ```js 75 | module.exports = require('./core'); 76 | ``` 77 | 78 | Then, delete the `core` directory. 79 | 80 | BetterDiscord's data is stored in the following locations: 81 | 82 | Platform | BetterDiscord data path 83 | -------------|--------------- 84 | Windows | `%APPDATA%`\BetterDiscord 85 | macOS | ~/Library/Preferences/BetterDiscord 86 | Linux | ~/.config/BetterDiscord 87 | 88 | To remove all of BetterDiscord's data, just delete that directory. 89 | 90 | > *BetterDiscord v2?* 91 | 92 | [BetterDiscord v2 is the new version of BetterDiscord currently in development.](https://github.com/JsSucks/BetterDiscordApp) If you'd like to help out with BetterDiscord v2, join the JsSucks Discord server. (Invite code `KYKwv4R`.) The only requirement is JavaScript/ES6 knowledge. 93 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | *.name 3 | devjs/.idea/devjs.iml 4 | *.bak 5 | *.bak.* 6 | *.xpi 7 | Firefox/data/js/jquery-2.1.4.min.js 8 | *.dev.* 9 | /nbproject/private/ 10 | node_modules 11 | .sass-cache 12 | /*.jiiks 13 | Installers/dotNet/bin/ 14 | Installers/dotNet/packages/ 15 | Installers/dotNet/dlls/ 16 | v2/dist/vendor/ 17 | v2/lib/static.js 18 | **/*.suo 19 | Installers/**/*/bin 20 | Installers/**/*/obj 21 | Installers/**/*/packages 22 | -------------------------------------------------------------------------------- /Firefox/@betterdiscord-0.0.1.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Firefox/@betterdiscord-0.0.1.xpi -------------------------------------------------------------------------------- /Firefox/README.md: -------------------------------------------------------------------------------- 1 | #BetterDiscord 2 | BetterDiscord enhances Discord with several features -------------------------------------------------------------------------------- /Firefox/betterdiscord-0.0.3-fx.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Firefox/betterdiscord-0.0.3-fx.xpi -------------------------------------------------------------------------------- /Firefox/data/css/main.css: -------------------------------------------------------------------------------- 1 | .guilds { 2 | background:red !important; 3 | } -------------------------------------------------------------------------------- /Firefox/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Firefox/icon.png -------------------------------------------------------------------------------- /Firefox/lib/BdPageMod.js: -------------------------------------------------------------------------------- 1 | "use sctrict" 2 | 3 | var pageMod = require('sdk/page-mod'); 4 | var data = require("sdk/self").data; 5 | 6 | function BdPageMod(options, callbacks) { 7 | pageMod.PageMod({ 8 | include: '*.discordapp.com', 9 | contentScriptFile: [data.url('../data/js/jquery-2.1.4.min.js'), data.url('../data/js/main.js')], 10 | contentStyleFile: [] 11 | }); 12 | } 13 | 14 | exports.BdPageMod = BdPageMod; -------------------------------------------------------------------------------- /Firefox/lib/BetterDiscord.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | var _bdPagemod = require('./BdPageMod.js'); 4 | 5 | function BetterDiscord(args) { 6 | _bdPagemod = new _bdPagemod.BdPageMod(); 7 | } 8 | 9 | exports.BetterDiscord = BetterDiscord; -------------------------------------------------------------------------------- /Firefox/lib/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _betterDiscord = require("./BetterDiscord.js"); 4 | 5 | function main(options, callbacks) { 6 | _betterDiscord = new _betterDiscord.BetterDiscord(); 7 | } 8 | 9 | exports.main = main; -------------------------------------------------------------------------------- /Firefox/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "BetterDiscord", 3 | "name": "betterdiscord", 4 | "version": "0.0.3", 5 | "description": "BetterDiscord enhances Discord with several features", 6 | "main": "lib/main", 7 | "author": "JiCode", 8 | "engines": { 9 | "firefox": ">=40.*" 10 | }, 11 | "license": "MIT", 12 | "keywords": [ 13 | "jetpack" 14 | ], 15 | "installs_allowed_from": [ 16 | "https://betterdiscord.net" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /Firefox/test/test-index.js: -------------------------------------------------------------------------------- 1 | var main = require("../"); 2 | 3 | exports["test main"] = function(assert) { 4 | assert.pass("Unit test running!"); 5 | }; 6 | 7 | exports["test main async"] = function(assert, done) { 8 | assert.pass("async Unit test running!"); 9 | done(); 10 | }; 11 | 12 | exports["test dummy"] = function(assert, done) { 13 | main.dummy("foo", function(text) { 14 | assert.ok((text === "foo"), "Is the text actually 'foo'"); 15 | done(); 16 | }); 17 | }; 18 | 19 | require("sdk/test").run(exports); 20 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | grunt.initConfig({ 4 | sass: { 5 | dist: { 6 | options: { 7 | style: 'expanded' 8 | }, 9 | files: { 10 | 'dev/css/main.css': 'dev/css/main.sass' 11 | } 12 | } 13 | }, 14 | concat: { 15 | js: { 16 | src: 'dev/js/*.js', 17 | dest: 'js/main.js' 18 | }, 19 | css: { 20 | src: 'dev/css/*.css', 21 | dest: 'css/main.css' 22 | } 23 | }, 24 | uglify: { 25 | options: { 26 | screwIE8: true 27 | }, 28 | js: { 29 | files: { 30 | 'js/main.min.js': ['js/main.js'] 31 | } 32 | } 33 | }, 34 | cssmin: { 35 | css: { 36 | src: 'css/main.css', 37 | dest: 'css/main.min.css' 38 | } 39 | } 40 | }); 41 | grunt.loadNpmTasks('grunt-contrib-concat'); 42 | grunt.loadNpmTasks('grunt-contrib-uglify'); 43 | grunt.loadNpmTasks('grunt-contrib-sass'); 44 | grunt.loadNpmTasks('grunt-css'); 45 | grunt.registerTask('default', ['sass', 'concat', 'uglify', 'cssmin']); 46 | }; -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Before* you create an issue, make sure you have: 2 | 3 | 1. Checked that that issue hasn't already been submitted. You can search open issues [here](https://github.com/Jiiks/BetterDiscordApp/issues). 4 | 2. Checked that there isn't an answer in either of the Discord servers (if you can access them - don't complain if you can't). 5 | 3. Checked that it isn't in the following list of frequently asked questions. 6 | 7 | If none of that helps you, delete the prefilled contents of this issue and ask whatever question you may have *in English so we can understand it*. 8 | 9 | ### FAQ 10 | 11 | > *BetterDiscord doesn't work.* 12 | > *BetterDiscord won't install.* 13 | > *BetterDiscord doesn't support macOS.* 14 | 15 | This branch isn't being updated anymore. Until BetterDiscord v2 is released you can use [Zach Rauen's fork](https://github.com/rauenzi/BetterDiscordApp). 16 | 17 | > *BetterDiscord doesn't support Linux.* 18 | 19 | There's an installer script for BetterDiscord on Linux available [here](https://github.com/bb010g/betterdiscordctl). 20 | 21 | > *BetterDiscord doesn't work in my browser.* 22 | 23 | The browser version doesn't exist anymore. Use the desktop client. 24 | 25 | > *BetterDiscord doesn't work on my phone.* 26 | 27 | ... and never will. BetterDiscord is a client modification for Discord's desktop Electron client. (Electron is a framework for making cross platform apps using web technologies. Basically the desktop client is just the web client in a specialised web browser.) 28 | 29 | > *Is there any security risks involved with installing BetterDiscord?* 30 | > *My friend was hacked after he/she installed BetterDiscord.* 31 | 32 | *Not by itself.* However, BetterDiscord allows loading plugins. Discord, BetterDiscord, and any plugins you install (even without enabling) have full access to your system as your local user account. (Including full access to your Discord account.) So, make sure you only download plugins from sources you trust. 33 | 34 | Also, please note that [BetterDocs](https://betterdocs.net) and other third-party sources by definition *are not* affiliated with BetterDiscord or it's developers. 35 | 36 | > *How do I install plugin [x]?* 37 | > *Is there a plugin to [x]?* 38 | > *Does [x] theme exist?* 39 | 40 | https://imgur.com/lczPQxW 41 | 42 | > *Minimal mode broke everything.* 43 | 44 | You can get back into Discord's settings to disable it by pressing `Control + ,` on Windows and Linux or `Command + ,` on macOS. 45 | 46 | > *How do I completely hide messages from people I've blocked?* 47 | 48 | Add this to your custom CSS: 49 | 50 | ```css 51 | .message-group-blocked { 52 | display: none !important; 53 | } 54 | ``` 55 | 56 | > *How do I remove BetterDiscord?* 57 | 58 | BetterDiscord is installed to the following locations: 59 | 60 | Platform | Discord path 61 | -------------|--------------- 62 | Windows | `%APPDATA%`\discord\0.0.`*`\modules\discord_desktop_core 63 | macOS | ~/Library/Application Support/discord/0.0.`*`/modules/discord_desktop_core 64 | Linux | ~/.config/discord/0.0.`*`/modules/discord_desktop_core 65 | 66 | To remove BetterDiscord, open the file `index.js` in that directory and make sure only this line exists: 67 | 68 | ```js 69 | module.exports = require('./core'); 70 | ``` 71 | 72 | Then, delete the `core` directory. 73 | 74 | BetterDiscord's data is stored in the following locations: 75 | 76 | Platform | BetterDiscord data path 77 | -------------|--------------- 78 | Windows | `%APPDATA%`\BetterDiscord 79 | macOS | ~/Library/Preferences/BetterDiscord 80 | Linux | ~/.config/BetterDiscord 81 | 82 | To remove all of BetterDiscord's data, just delete that directory. 83 | 84 | > *BetterDiscord v2?* 85 | 86 | [BetterDiscord v2 is the new version of BetterDiscord currently in development.](https://github.com/JsSucks/BetterDiscordApp) If you'd like to help out with BetterDiscord v2, join the JsSucks Discord server. (Invite code `KYKwv4R`.) The only requirement is JavaScript/ES6 knowledge. 87 | -------------------------------------------------------------------------------- /Installers/Electron/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | pack.bat 3 | run.bat -------------------------------------------------------------------------------- /Installers/Electron/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "betterdiscordinstaller", 3 | "description": "Better Discord installer.", 4 | "version": "0.1.1", 5 | "homepage": "https://github.com/Jiiks/BetterDiscordApp", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "dependencies": { 9 | "fs-extra": "^0.30.0", 10 | "readline": "^1.3.0", 11 | "open": "^0.0.5", 12 | "request": "^2.72.0", 13 | "path": "^0.12.7", 14 | "walk": "^2.3.9", 15 | "unzip": "^0.1.11" 16 | }, 17 | "devDependencies": { 18 | "electron-prebuilt": "~1.2.8" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Installers/Electron/src/asar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const 4 | fs = require('fs'), 5 | path = require('path'), 6 | walk = require('walk'), 7 | p = require('path'); 8 | 9 | fs.mkdirPSync = function(dirPath) { 10 | try { 11 | fs.mkdirSync(dirPath); 12 | } catch(err) { 13 | if(err.errno === -4058 || err.errno === -2) { 14 | fs.mkdirPSync(path.dirname(dirPath)); 15 | fs.mkdirPSync(dirPath); 16 | } else if(err.errno === -4075) { 17 | return "EXIST"; 18 | } else { 19 | return "NOT OK"; 20 | } 21 | } 22 | return "OK"; 23 | } 24 | 25 | class Asar { 26 | 27 | constructor(filePath) { 28 | this.path = filePath; 29 | this.files = []; 30 | } 31 | 32 | extract(statusCb, progressCb, cb) { 33 | this.walker = walk.walk(this.path, { followLinks: false }); 34 | statusCb("Creating Directories"); 35 | this.walker.on('file', (root, stat, next) => { 36 | this.files.push(`${root}/${stat.name}`); 37 | try { 38 | fs.statSync(root.replace("app.asar", "app")); 39 | } catch(err) { 40 | fs.mkdirPSync(root.replace("app.asar", "app")); 41 | } 42 | next(); 43 | }); 44 | 45 | this.walker.on('end', () => { 46 | var self = this; 47 | statusCb("Copying files"); 48 | var p = 1; 49 | var filecount = this.files.length; 50 | 51 | function copy(files, index) { 52 | if(index >= filecount) { 53 | statusCb("Finished extracting app package"); 54 | cb(null); 55 | return; 56 | } 57 | setTimeout(() => { self.copyfile(files, index, copy) }, 1); 58 | progressCb(index, filecount); 59 | } 60 | 61 | copy(this.files, 0); 62 | }); 63 | } 64 | 65 | copyfile(files, index, cb) { 66 | fs.writeFileSync(files[index].replace("app.asar", "app"), fs.readFileSync(files[index])); 67 | cb(files, index+1); 68 | } 69 | } 70 | 71 | module.exports = Asar; -------------------------------------------------------------------------------- /Installers/Electron/src/data/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 |
13 |
14 |
15 | Error! 16 |
17 |
18 |
19 |
20 |
21 |
22 | 23 |
24 | 25 | 36 | -------------------------------------------------------------------------------- /Installers/Electron/src/data/font/Inconsolata.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/Electron/src/data/font/Inconsolata.woff2 -------------------------------------------------------------------------------- /Installers/Electron/src/data/font/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/Electron/src/data/font/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /Installers/Electron/src/data/js/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const ipcRenderer = require('electron').ipcRenderer; 4 | 5 | var config = { 6 | urls: { 7 | package: "https://github.com/Jiiks/BetterDiscordApp/archive/stable16.zip", 8 | finish: "https://betterdiscord.net/installed" 9 | }, 10 | discord: { 11 | lastKnownVersion: "0.0.291" 12 | }, 13 | import: "BetterDiscordApp-stable16", 14 | cache: [ 15 | "emotes_bttv.json", 16 | "emotes_bttv_2.json", 17 | "emotes_ffz.json", 18 | "emotes_twitch_global.json", 19 | "emotes_twitch_subscriber.json", 20 | "user.json" 21 | ] 22 | }; 23 | 24 | (function() { 25 | //Pass latest config to core application 26 | ipcSendAsync("config", config); 27 | //Get Discord installation path 28 | ipcSendAsync("get", "discordpath" ); 29 | //Get BetterDiscord installation path 30 | ipcSendAsync("get", "libpath"); 31 | })(); 32 | 33 | 34 | //Listeners 35 | (function() { 36 | 37 | $("#cd").on("change", () => { 38 | $("#next").prop("disabled", !$("#cd").prop("checked")); 39 | }); 40 | 41 | var currentPanel = 0; 42 | 43 | function switchPanel() { 44 | var container = $(".panel-container"); 45 | var main = $(".main-container"); 46 | main.removeClass(); 47 | main.addClass(`main-container panel-${currentPanel}`) 48 | switch(currentPanel) { 49 | case 0: 50 | $("#next").text("Next"); 51 | //$("#next").prop("disabled", !$("#cd").prop("checked")); 52 | break; 53 | case 1: 54 | $("#next").text("Next"); 55 | //$("#next").prop("disabled", !$("#accept").prop("checked")); 56 | break; 57 | case 2: 58 | $("#next").text("Install"); 59 | $("#cancel").text("Cancel"); 60 | break; 61 | case 3: 62 | $("#cancel").text("Abort"); 63 | ipcSendAsync("install"); 64 | break; 65 | } 66 | } 67 | 68 | $("#next").on("click", function() { 69 | currentPanel++; 70 | switchPanel(); 71 | }); 72 | 73 | $("#back").on("click", function() { 74 | currentPanel--; 75 | switchPanel(); 76 | }); 77 | 78 | $("#cancel").on("click", function() { 79 | $("#quit").show(); 80 | }); 81 | 82 | $("#uninstall").on("click", function() { 83 | 84 | }); 85 | 86 | $("#accept").on("change", function() { 87 | // $("#next").prop("disabled", !$(this).prop("checked")); 88 | }); 89 | 90 | $("#decline").on("change", function() { 91 | // $("#next").prop("disabled", $(this).prop("checked")); 92 | }); 93 | 94 | $("#licensetext").on("scroll", function() { 95 | var e = $(this); 96 | if(e.height() + e.scrollTop() >= e[0].scrollHeight) { 97 | $("#accept").prop("disabled", false); 98 | } else { 99 | $("#accept").prop("disabled", true); 100 | $("#decline").prop("checked", true) 101 | // $("#next").prop("disabled", true); 102 | } 103 | }); 104 | 105 | $(".modal").on("click", function(e) { 106 | if(e.target.className !== "modal") return; 107 | $(this).hide(); 108 | }); 109 | 110 | $("#modal-cancel").on("click", function() { 111 | $(".modal").hide(); 112 | }); 113 | 114 | $("#modal-exit").on("click", function() { 115 | ipcRenderer.send("async", {arg: "quit", data: []}); 116 | }); 117 | 118 | $("#path").on("click", () => { 119 | ipcRenderer.send("async", { arg: "browsedialog", data: "discordpath" }); 120 | }); 121 | 122 | $("#libpathbtn").on("click", () => { 123 | ipcRenderer.send("async", { arg: "browsedialog", data: "libpath" }); 124 | }); 125 | 126 | $("#advanced-settings").on("click", function() { 127 | currentPanel = "advanced"; 128 | switchPanel(); 129 | }); 130 | 131 | $("#advanced-close").on("click", function() { 132 | var main = $(".main-container"); 133 | currentPanel = 2; 134 | switchPanel(); 135 | }); 136 | 137 | })(); 138 | 139 | ipcRenderer.on("async-reply", (event, arg) => { 140 | 141 | var data = arg.data; 142 | arg = arg.arg; 143 | 144 | switch(arg) { 145 | case "discordpath": 146 | $("#discordPath").val(data); 147 | break; 148 | case "libpath": 149 | $("#libpath").val(data); 150 | break; 151 | } 152 | 153 | }); 154 | 155 | 156 | /*ipcRenderer.on('async-reply', (event, arg) => { 157 | switch(arg.arg) { 158 | case "exists": 159 | switch(arg.file) { 160 | case "install": 161 | if(arg.exists) { 162 | appendLog("Located app package"); 163 | appendLog("Downloading latest BetterDiscord package"); 164 | ipcRenderer.send('async', '{"arg": "download", "package": "https://github.com/Jiiks/BetterDiscordApp/archive/stable16.zip" }'); 165 | } else { 166 | appendLog("Unable to locate app.asar. Check your install path."); 167 | } 168 | } 169 | break; 170 | case "discordpath": 171 | $("#discordPath").val(arg.path); 172 | break; 173 | case "locate-app.asar": 174 | appendLog(arg.data); 175 | break; 176 | } 177 | });*/ 178 | 179 | function ipcSendAsync(arg, data) { 180 | ipcRenderer.send("async", { arg: arg, data: data }); 181 | } 182 | 183 | function install() { 184 | appendLog("Initiating installation"); 185 | appendLog("Locating Discord package"); 186 | ipcRenderer.send('async', { "arg": "install" }); 187 | } 188 | 189 | function appendLog(text) { 190 | var log = $("#log"); 191 | log.append(text+"\n"); 192 | var sh = log[0].scrollHeight - 40; 193 | if(log.height() + log.scrollTop() >= sh) { 194 | log.scrollTop(sh); 195 | } 196 | } 197 | 198 | function updatePbar(cur, max) { 199 | var pbar = $("#logpbar"); 200 | pbar.val(cur); 201 | pbar.prop("max", max); 202 | } -------------------------------------------------------------------------------- /Installers/Electron/src/data/js/splash.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const ipcRenderer = require('electron').ipcRenderer; 4 | 5 | ipcRenderer.on('async-reply', (event, arg) => { 6 | switch(arg) { 7 | case "update": 8 | $(".spinnertext").text("Downloading Update"); 9 | break; 10 | } 11 | }); 12 | 13 | $(function() { 14 | ipcRenderer.send('async', '{ "arg": "update" }'); 15 | }); -------------------------------------------------------------------------------- /Installers/Electron/src/data/splash.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 | Checking for updates... 15 | 16 | -------------------------------------------------------------------------------- /Installers/Electron/src/data/vi.json: -------------------------------------------------------------------------------- 1 | { 2 | "windows": { 3 | "version": "0.1.0" 4 | }, 5 | "osx": { 6 | "version": "0.1.1" 7 | } 8 | } -------------------------------------------------------------------------------- /Installers/Electron/src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var devMode = false; 4 | 5 | const 6 | electron = require('electron'), 7 | app = electron.app, 8 | BrowserWindow = electron.BrowserWindow, 9 | ipcMain = electron.ipcMain, 10 | utils = require('./utils'), 11 | _utils = new utils(); 12 | 13 | var 14 | mainWindow, 15 | windowOptions = { 16 | width: 300, 17 | height: 100, 18 | fullscreenable: false, 19 | maximizable: false, 20 | frame: false, 21 | resizable: devMode ? true : false, 22 | alwaysOnTop: devMode ? true : false, 23 | transparent: false 24 | }; 25 | 26 | 27 | class Index { 28 | 29 | constructor() { 30 | app.on("ready", () => this.appReady()); 31 | } 32 | 33 | appReady() { 34 | mainWindow = new BrowserWindow(windowOptions); 35 | this.loadInstaller(); 36 | } 37 | 38 | loadInstaller() { 39 | this.installer = require('./installer_index'); 40 | this.installerInstance = new this.installer(app, mainWindow, ipcMain, _utils); 41 | } 42 | 43 | } 44 | 45 | module.exports = new Index(); -------------------------------------------------------------------------------- /Installers/Electron/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Install", 3 | "description": "Better Discord enhances Discord.", 4 | "version": "0.1.1", 5 | "homepage": "https://github.com/Jiiks/BetterDiscordApp", 6 | "license": "MIT", 7 | "devDependencies": { 8 | "electron-prebuilt": "^1.0.0" 9 | } 10 | } -------------------------------------------------------------------------------- /Installers/Electron/src/updater.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class Updater { 4 | 5 | constructor(utils) { 6 | this.utils = utils; 7 | } 8 | 9 | update() { 10 | var self = this; 11 | var promises = [ 12 | new Promise((resolve, reject) => { 13 | downloadResource("/Jiiks/BetterDiscordApp/master/Installers/Electron/src/data/index.html", (error, data) 14 | if(error) { 15 | error(data, true); 16 | reject(); 17 | return; 18 | } 19 | self.utils.log("Succesfully loaded index.html"); 20 | resolve(); 21 | }); 22 | }), 23 | new Promise((resolve, reject) => { 24 | downloadResource("/Jiiks/BetterDiscordApp/master/Installers/Electron/src/data/js/main.js", (error, data) 25 | if(error) { 26 | error(data, true); 27 | reject(); 28 | return; 29 | } 30 | self.utils.log("Succesfully loaded main.js"); 31 | resolve(); 32 | }); 33 | }), 34 | new Promise((resolve, reject) => { 35 | downloadResource("/Jiiks/BetterDiscordApp/master/Installers/Electron/src/data/css/main.css", (error, dat 36 | if(error) { 37 | error(data, true); 38 | reject(); 39 | return; 40 | } 41 | self.utils.log("Succesfully loaded main.css"); 42 | resolve(); 43 | }); 44 | }) 45 | ]; 46 | return Promise.all(promises); 47 | } 48 | 49 | checkForUpdates(okCb, errorCb) { 50 | _utils.downloadResource("/Jiiks/BetterDiscordApp/master/Installers/Electron/src/data/vi.json", (error, data) => { 51 | if(error) { 52 | errorCb(data); 53 | return; 54 | } 55 | 56 | try { 57 | data = JSON.parse(data); 58 | }catch(err) { 59 | errorCb(err); 60 | return; 61 | } 62 | 63 | switch(platform) { 64 | case "win32": 65 | okCb(data.windows.version > vi.windows.version); 66 | break; 67 | case "darwin": 68 | okCb(data.osx.version > vi.osx.version); 69 | break; 70 | } 71 | }); 72 | } 73 | } 74 | 75 | module.exports = Updater; -------------------------------------------------------------------------------- /Installers/Electron/src/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const 4 | https = require('https'), 5 | fs = require('fs'), 6 | eol = require('os').EOL, 7 | platform = (process.platform !== "win32" && process.platform !== "darwin") ? "linux" : process.platform; 8 | 9 | class Utils { 10 | 11 | constructor() { 12 | this.logs = ""; 13 | } 14 | 15 | log(message) { 16 | var d = new Date(); 17 | var ds = ("00" + (d.getDate() + 1)).slice(-2) + "/" + 18 | ("00" + d.getMonth()).slice(-2) + "/" + 19 | d.getFullYear() + " " + 20 | ("00" + d.getHours()).slice(-2) + ":" + 21 | ("00" + d.getMinutes()).slice(-2) + ":" + 22 | ("00" + d.getSeconds()).slice(-2); 23 | console.log(`[${ds}] ${message}`); 24 | this.logs += `[${ds}] ${message}${eol}`; 25 | this.saveLogs(); 26 | } 27 | 28 | printLogs() { 29 | console.log(this.logs); 30 | } 31 | 32 | saveLogs() { 33 | fs.writeFileSync("logs.log", this.logs); 34 | } 35 | 36 | downloadResource(resource, callback, host) { 37 | https.get({ 38 | host: host || "raw.githubusercontent.com", 39 | path: resource, 40 | headers: { 'user-agent': 'Mozilla/5.0' } 41 | }, 42 | (response) => { 43 | var data = ""; 44 | response.on("data", (chunk) => { 45 | data += chunk; 46 | }); 47 | response.on("end", () => { 48 | callback(false, data); 49 | }); 50 | response.on("error", (e) => { 51 | callback(true, e); 52 | }); 53 | }).on('error', (e) => { 54 | callback(true, e); 55 | }); 56 | } 57 | 58 | installPath(lastKnownVersion) { 59 | 60 | return { 61 | "win32": () => { 62 | var hver = lastKnownVersion; 63 | var path = `${process.env.LOCALAPPDATA}/Discord/app-${lastKnownVersion}\\`; 64 | fs.readdirSync(`${process.env.LOCALAPPDATA}/Discord/`).filter(function(file) { 65 | var tpath = `${process.env.LOCALAPPDATA}/Discord/${file}`; 66 | if(!fs.statSync(tpath).isDirectory()) return; 67 | 68 | if(!file.startsWith("app-")) return; 69 | var ver = file.replace("app-", ""); 70 | if(ver < hver) return; 71 | hver = ver; 72 | path = tpath; 73 | }); 74 | return path; 75 | }, 76 | "darwin": () => "/Applications/Discord.app/Contents", 77 | "linux": () => "/usr/share/discord" 78 | }[platform](); 79 | 80 | } 81 | 82 | libPath() { 83 | return { 84 | "win32": () => { 85 | return `${process.env.APPDATA}/BetterDiscord/lib`; 86 | }, 87 | "darwin": () => { 88 | return `${process.env.HOME}/.local/share/BetterDiscord`; 89 | }, 90 | "linux": () => { 91 | // FIXME: for a non-root user, a path like OSX's makes more sense 92 | return "/usr/local/share/BetterDiscord"; 93 | } 94 | }[platform](); 95 | } 96 | } 97 | 98 | module.exports = Utils; -------------------------------------------------------------------------------- /Installers/Node/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "init": "init" 3 | } -------------------------------------------------------------------------------- /Installers/Node/install.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | where node.exe >nul 2>nul 3 | if %errorlevel%==1 ( 4 | echo "Node.exe not found, opening your browser..." 5 | start "" "https://nodejs.org/dist/latest/win-x86/node.exe" 6 | pause 7 | ) else ( 8 | taskkill /f /im "Discord.exe" >nul 2>nul 9 | cmd /k node.exe index.js 10 | ) 11 | exit 12 | -------------------------------------------------------------------------------- /Installers/Node/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # As there is no Linux support, this script assumes OS X as the host system. 3 | 4 | command -v node > /dev/null || (echo 'Node not found, please download it!' && open 'https://nodejs.org/en/' && sleep 5 && exit) 5 | 6 | node index.js 7 | exit -------------------------------------------------------------------------------- /Installers/dotNet/.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Installers/dotNet/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 19 | !packages/*/build/ 20 | 21 | # MSTest test Results 22 | [Tt]est[Rr]esult*/ 23 | [Bb]uild[Ll]og.* 24 | 25 | *_i.c 26 | *_p.c 27 | *.ilk 28 | *.meta 29 | *.obj 30 | *.pch 31 | *.pdb 32 | *.pgc 33 | *.pgd 34 | *.rsp 35 | *.sbr 36 | *.tlb 37 | *.tli 38 | *.tlh 39 | *.tmp 40 | *.tmp_proj 41 | *.log 42 | *.vspscc 43 | *.vssscc 44 | .builds 45 | *.pidb 46 | *.log 47 | *.scc 48 | 49 | # Visual C++ cache files 50 | ipch/ 51 | *.aps 52 | *.ncb 53 | *.opensdf 54 | *.sdf 55 | *.cachefile 56 | 57 | # Visual Studio profiler 58 | *.psess 59 | *.vsp 60 | *.vspx 61 | 62 | # Guidance Automation Toolkit 63 | *.gpState 64 | 65 | # ReSharper is a .NET coding add-in 66 | _ReSharper*/ 67 | *.[Rr]e[Ss]harper 68 | 69 | # TeamCity is a build add-in 70 | _TeamCity* 71 | 72 | # DotCover is a Code Coverage Tool 73 | *.dotCover 74 | 75 | # NCrunch 76 | *.ncrunch* 77 | .*crunch*.local.xml 78 | 79 | # Installshield output folder 80 | [Ee]xpress/ 81 | 82 | # DocProject is a documentation generator add-in 83 | DocProject/buildhelp/ 84 | DocProject/Help/*.HxT 85 | DocProject/Help/*.HxC 86 | DocProject/Help/*.hhc 87 | DocProject/Help/*.hhk 88 | DocProject/Help/*.hhp 89 | DocProject/Help/Html2 90 | DocProject/Help/html 91 | 92 | # Click-Once directory 93 | publish/ 94 | 95 | # Publish Web Output 96 | *.Publish.xml 97 | 98 | # NuGet Packages Directory 99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 100 | #packages/ 101 | 102 | # Windows Azure Build Output 103 | csx 104 | *.build.csdef 105 | 106 | # Windows Store app package directory 107 | AppPackages/ 108 | 109 | # Others 110 | sql/ 111 | *.Cache 112 | ClientBin/ 113 | [Ss]tyle[Cc]op.* 114 | ~$* 115 | *~ 116 | *.dbmdl 117 | *.[Pp]ublish.xml 118 | *.pfx 119 | *.publishsettings 120 | 121 | # RIA/Silverlight projects 122 | Generated_Code/ 123 | 124 | # Backup & report files from converting an old project file to a newer 125 | # Visual Studio version. Backup files are not needed, because we have git ;-) 126 | _UpgradeReport_Files/ 127 | Backup*/ 128 | UpgradeLog*.XML 129 | UpgradeLog*.htm 130 | 131 | # SQL Server files 132 | App_Data/*.mdf 133 | App_Data/*.ldf 134 | 135 | 136 | #LightSwitch generated files 137 | GeneratedArtifacts/ 138 | _Pvt_Extensions/ 139 | ModelManifest.xml 140 | 141 | # ========================= 142 | # Windows detritus 143 | # ========================= 144 | 145 | # Windows image file caches 146 | Thumbs.db 147 | ehthumbs.db 148 | 149 | # Folder config file 150 | Desktop.ini 151 | 152 | # Recycle Bin used on file shares 153 | $RECYCLE.BIN/ 154 | 155 | # Mac desktop service store files 156 | .DS_Store 157 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BetterDiscordWI", "BetterDiscordWI\BetterDiscordWI.csproj", "{469F7547-7664-4DE8-A568-E89525981539}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {469F7547-7664-4DE8-A568-E89525981539}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {469F7547-7664-4DE8-A568-E89525981539}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {469F7547-7664-4DE8-A568-E89525981539}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {469F7547-7664-4DE8-A568-E89525981539}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/App.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/BetterDiscord-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/dotNet/BetterDiscordWI/BetterDiscord-icon.ico -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/FormMain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | using System.Xml; 5 | using BetterDiscordWI.panels; 6 | 7 | namespace BetterDiscordWI { 8 | public partial class FormMain : Form { 9 | 10 | private readonly IPanel[] _panels = { new Panel0(), new Panel1(), new Panel2() }; 11 | private int _index; 12 | 13 | public string DiscordPath; 14 | public bool RestartDiscord = false; 15 | public string Sha; 16 | public bool Finished = false; 17 | 18 | public XmlNodeList ResourceList; 19 | 20 | public FormMain() { 21 | InitializeComponent(); 22 | 23 | Sha = Utils.GetHash(); 24 | 25 | if (Sha.Length < 1) { 26 | MessageBox.Show(@"Failed to get sha", @"Error", MessageBoxButtons.OK); 27 | Environment.Exit(0); 28 | } 29 | 30 | foreach (IPanel ipanel in _panels) { 31 | panelContainer.Controls.Add((UserControl)ipanel); 32 | ((UserControl)ipanel).Dock = DockStyle.Fill; 33 | ((UserControl)ipanel).Hide(); 34 | } 35 | ((UserControl)_panels[_index]).Show(); 36 | _panels[_index].SetVisible(); 37 | 38 | btnCancel.Click += (sender, args) => Close(); 39 | btnNext.Click += (sender, args) => _panels[_index].BtnNext(); 40 | btnBack.Click += (sender, args) => _panels[_index].BtnPrev(); 41 | } 42 | 43 | public void SwitchPanel(int index) { 44 | ((UserControl)_panels[_index]).Hide(); 45 | _index = index; 46 | ((UserControl)_panels[_index]).Show(); 47 | _panels[_index].SetVisible(); 48 | } 49 | 50 | protected override void OnFormClosing(FormClosingEventArgs e) { 51 | if (Finished) return; 52 | DialogResult dr = MessageBox.Show(@"Setup is not complete. If you exit now, BetterDiscord will not be installed. Exit Setup?", @"Exit Setup?", MessageBoxButtons.YesNo); 53 | if (dr == DialogResult.No) { 54 | e.Cancel = true; 55 | } 56 | } 57 | 58 | readonly Pen _borderPen = new Pen(Color.FromArgb(160, 160, 160)); 59 | protected override void OnPaint(PaintEventArgs e) { 60 | Graphics g = e.Graphics; 61 | g.FillRectangle(SystemBrushes.Window, new Rectangle(0, 0, Width, 50)); 62 | g.DrawLine(_borderPen, 0, 50, Width, 50); 63 | g.DrawLine(SystemPens.Window, 0, 51, Width, 51); 64 | 65 | g.DrawLine(_borderPen, 0, 310, Width, 310); 66 | g.DrawLine(SystemPens.Window, 0, 311, Width, 311); 67 | 68 | base.OnPaint(e); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace BetterDiscordWI 5 | { 6 | static class Program 7 | { 8 | /// 9 | /// The main entry point for the application. 10 | /// 11 | [STAThread] 12 | static void Main() 13 | { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault(false); 16 | Application.Run(new FormMain()); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("BetterDiscordWI")] 9 | [assembly: AssemblyDescription("Better Discord Windows Installer")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Jiiks")] 12 | [assembly: AssemblyProduct("BetterDiscordWI")] 13 | [assembly: AssemblyCopyright("Copyright © 2015-2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("17adafc9-c3e6-49c2-b2c9-d6866e7f4f23")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("0.2.8.0")] 36 | [assembly: AssemblyFileVersion("0.2.8.0")] 37 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace BetterDiscordWI.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BetterDiscordWI.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap bd_logo_64x64 { 67 | get { 68 | object obj = ResourceManager.GetObject("bd_logo_64x64", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap bd_logo_64x64_nobg { 77 | get { 78 | object obj = ResourceManager.GetObject("bd_logo_64x64_nobg", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap bd_logo_large_nobg { 87 | get { 88 | object obj = ResourceManager.GetObject("bd_logo_large_nobg", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap bd_logo2 { 97 | get { 98 | object obj = ResourceManager.GetObject("bd_logo2", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace BetterDiscordWI.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/Resources/BetterDiscord-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/dotNet/BetterDiscordWI/Resources/BetterDiscord-icon.ico -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/Resources/bd_logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/dotNet/BetterDiscordWI/Resources/bd_logo2.png -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/Resources/bd_logo_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/dotNet/BetterDiscordWI/Resources/bd_logo_64x64.png -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/Resources/bd_logo_64x64_nobg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/dotNet/BetterDiscordWI/Resources/bd_logo_64x64_nobg.png -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/Resources/bd_logo_large_nobg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/dotNet/BetterDiscordWI/Resources/bd_logo_large_nobg.png -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Net; 4 | using System.Threading; 5 | using System.Windows.Forms; 6 | 7 | namespace BetterDiscordWI 8 | { 9 | class Utils 10 | { 11 | public void StartDownload(ProgressBar pb, string url, string name) 12 | { 13 | Thread t = new Thread(() => 14 | { 15 | WebClient webClient = new WebClient {Headers = {["User-Agent"] = "Mozilla/5.0"}}; 16 | webClient.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs args) 17 | { 18 | double percentage = (double.Parse(args.BytesReceived.ToString()) /double.Parse(args.TotalBytesToReceive.ToString())) * 100; 19 | Debug.Print(percentage.ToString()); 20 | pb.Invoke((MethodInvoker) delegate 21 | { 22 | pb.Value = (int)Math.Truncate(percentage); 23 | }); 24 | 25 | }; 26 | 27 | 28 | webClient.DownloadFile(new Uri(url), Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\BetterDiscord\\temp\\" + name); 29 | 30 | }); 31 | 32 | t.Start(); 33 | } 34 | 35 | public static string GetHash() 36 | { 37 | WebClient wc = new WebClient {Headers = {["User-Agent"] = "Mozilla/5.0"}}; 38 | string result = wc.DownloadString(@"https://api.github.com/repos/Jiiks/BetterDiscordApp/commits/master"); 39 | 40 | int start = result.IndexOf("{\"sha\":"); 41 | int end = result.IndexOf("\",\""); 42 | 43 | return result.Substring(start + 8, end - 8); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/components/CTextBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Forms; 7 | 8 | namespace BetterDiscordWI.components 9 | { 10 | class CTextBox : TextBox 11 | { 12 | 13 | public bool CAutoSize 14 | { 15 | get { return AutoSize; } 16 | set { AutoSize = value; } 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/panels/IPanel.cs: -------------------------------------------------------------------------------- 1 | namespace BetterDiscordWI.panels { 2 | interface IPanel { 3 | void SetVisible(); 4 | FormMain GetParent(); 5 | void BtnNext(); 6 | void BtnPrev(); 7 | } 8 | } -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/panels/Panel0.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace BetterDiscordWI.panels 2 | { 3 | partial class Panel0 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Panel0)); 32 | this.label2 = new System.Windows.Forms.Label(); 33 | this.richTextBox1 = new System.Windows.Forms.RichTextBox(); 34 | this.radioDeclineLicense = new System.Windows.Forms.RadioButton(); 35 | this.radioAcceptLicense = new System.Windows.Forms.RadioButton(); 36 | this.SuspendLayout(); 37 | // 38 | // label2 39 | // 40 | this.label2.Location = new System.Drawing.Point(35, 18); 41 | this.label2.Name = "label2"; 42 | this.label2.Size = new System.Drawing.Size(455, 31); 43 | this.label2.TabIndex = 5; 44 | this.label2.Text = "Please read the following License Agreement and accept the terms before continuin" + 45 | "g the installation."; 46 | // 47 | // richTextBox1 48 | // 49 | this.richTextBox1.Location = new System.Drawing.Point(38, 54); 50 | this.richTextBox1.Name = "richTextBox1"; 51 | this.richTextBox1.ReadOnly = true; 52 | this.richTextBox1.Size = new System.Drawing.Size(452, 169); 53 | this.richTextBox1.TabIndex = 4; 54 | this.richTextBox1.Text = resources.GetString("richTextBox1.Text"); 55 | // 56 | // radioDeclineLicense 57 | // 58 | this.radioDeclineLicense.AutoSize = true; 59 | this.radioDeclineLicense.Checked = true; 60 | this.radioDeclineLicense.Location = new System.Drawing.Point(108, 229); 61 | this.radioDeclineLicense.Name = "radioDeclineLicense"; 62 | this.radioDeclineLicense.Size = new System.Drawing.Size(61, 17); 63 | this.radioDeclineLicense.TabIndex = 8; 64 | this.radioDeclineLicense.TabStop = true; 65 | this.radioDeclineLicense.Text = "Decline"; 66 | this.radioDeclineLicense.UseVisualStyleBackColor = true; 67 | // 68 | // radioAcceptLicense 69 | // 70 | this.radioAcceptLicense.AutoSize = true; 71 | this.radioAcceptLicense.Location = new System.Drawing.Point(38, 229); 72 | this.radioAcceptLicense.Name = "radioAcceptLicense"; 73 | this.radioAcceptLicense.Size = new System.Drawing.Size(59, 17); 74 | this.radioAcceptLicense.TabIndex = 7; 75 | this.radioAcceptLicense.Text = "Accept"; 76 | this.radioAcceptLicense.UseVisualStyleBackColor = true; 77 | // 78 | // Panel0 79 | // 80 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 81 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 82 | this.Controls.Add(this.radioDeclineLicense); 83 | this.Controls.Add(this.radioAcceptLicense); 84 | this.Controls.Add(this.label2); 85 | this.Controls.Add(this.richTextBox1); 86 | this.Name = "Panel0"; 87 | this.Size = new System.Drawing.Size(524, 258); 88 | this.ResumeLayout(false); 89 | this.PerformLayout(); 90 | 91 | } 92 | 93 | #endregion 94 | 95 | private System.Windows.Forms.Label label2; 96 | private System.Windows.Forms.RichTextBox richTextBox1; 97 | private System.Windows.Forms.RadioButton radioDeclineLicense; 98 | private System.Windows.Forms.RadioButton radioAcceptLicense; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/panels/Panel0.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace BetterDiscordWI.panels { 4 | public partial class Panel0 : UserControl, IPanel { 5 | public Panel0() { 6 | InitializeComponent(); 7 | 8 | radioAcceptLicense.CheckedChanged += (sender, args) => { 9 | GetParent().btnNext.Enabled = radioAcceptLicense.Checked; 10 | }; 11 | } 12 | 13 | public void SetVisible() { 14 | GetParent().btnBack.Visible = false; 15 | GetParent().btnNext.Enabled = false; 16 | GetParent().btnNext.Text = @"Next >"; 17 | GetParent().lblPanelTitle.Text = @"BetterDiscord License Agreement"; 18 | GetParent().btnNext.Enabled = radioAcceptLicense.Checked; 19 | } 20 | 21 | public FormMain GetParent() { 22 | return (FormMain)ParentForm; 23 | } 24 | 25 | public void BtnNext() { 26 | GetParent().SwitchPanel(1); 27 | } 28 | 29 | public void BtnPrev() {} 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/panels/Panel1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Windows.Forms; 5 | 6 | namespace BetterDiscordWI.panels { 7 | public partial class Panel1: UserControl, IPanel { 8 | public Panel1() { 9 | InitializeComponent(); 10 | } 11 | 12 | public void SetVisible() { 13 | 14 | GetParent().btnBack.Visible = true; 15 | GetParent().btnNext.Enabled = true; 16 | GetParent().btnBack.Enabled = true; 17 | GetParent().btnNext.Text = @"Install"; 18 | GetParent().lblPanelTitle.Text = @"BetterDiscord Installation"; 19 | 20 | PickVersion(); 21 | } 22 | 23 | public FormMain GetParent() { 24 | return (FormMain)ParentForm; 25 | } 26 | 27 | public void BtnNext() { 28 | GetParent().DiscordPath = tbPath.Text; 29 | GetParent().RestartDiscord = cbRestart.Checked; 30 | GetParent().SwitchPanel(2); 31 | } 32 | 33 | public void BtnPrev() { 34 | GetParent().SwitchPanel(0); 35 | } 36 | 37 | private void btnBrowser_Click(object sender, EventArgs e) { 38 | FolderBrowserDialog fbd = new FolderBrowserDialog { SelectedPath = tbPath.Text }; 39 | fbd.ShowDialog(GetParent()); 40 | 41 | tbPath.Text = fbd.SelectedPath; 42 | } 43 | 44 | private void checkBox1_CheckedChanged(object sender, EventArgs e) { 45 | PickVersion(); 46 | } 47 | 48 | private void checkBox2_CheckedChanged(object sender, EventArgs e) { 49 | PickVersion(); 50 | } 51 | 52 | private void PickVersion() { 53 | string dirPath; 54 | if(checkBox1.Checked) { 55 | dirPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\DiscordCanary"; 56 | if(!Directory.Exists(dirPath)) checkBox1.Checked = false; 57 | 58 | checkBox2.Checked = false; 59 | } else if(checkBox2.Checked) { 60 | dirPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\DiscordPTB"; 61 | if(!Directory.Exists(dirPath)) checkBox2.Checked = false; 62 | 63 | checkBox1.Checked = false; 64 | } else { 65 | dirPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Discord"; 66 | } 67 | 68 | if (!Directory.Exists(dirPath)) return; 69 | string[] directories = Directory.GetDirectories(dirPath); 70 | 71 | string highestVersion = null; 72 | 73 | foreach(string s in directories) { 74 | Debug.Print(s); 75 | if(!s.Contains("app-")) 76 | continue; 77 | if(string.IsNullOrEmpty(highestVersion)) { 78 | highestVersion = s; 79 | continue; 80 | } 81 | 82 | if(string.CompareOrdinal(s, highestVersion) > 0) { 83 | highestVersion = s; 84 | } 85 | } 86 | 87 | tbPath.Text = highestVersion; 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/panels/Panel1.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/panels/Panel2.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace BetterDiscordWI.panels 2 | { 3 | partial class Panel2 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.pbMain = new System.Windows.Forms.ProgressBar(); 32 | this.rtLog = new System.Windows.Forms.RichTextBox(); 33 | this.SuspendLayout(); 34 | // 35 | // pbMain 36 | // 37 | this.pbMain.Location = new System.Drawing.Point(3, 267); 38 | this.pbMain.Name = "pbMain"; 39 | this.pbMain.Size = new System.Drawing.Size(518, 16); 40 | this.pbMain.TabIndex = 0; 41 | // 42 | // rtLog 43 | // 44 | this.rtLog.Location = new System.Drawing.Point(3, 3); 45 | this.rtLog.Name = "rtLog"; 46 | this.rtLog.Size = new System.Drawing.Size(518, 252); 47 | this.rtLog.TabIndex = 1; 48 | this.rtLog.Text = ""; 49 | // 50 | // Panel2 51 | // 52 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 53 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 54 | this.Controls.Add(this.rtLog); 55 | this.Controls.Add(this.pbMain); 56 | this.Name = "Panel2"; 57 | this.Size = new System.Drawing.Size(524, 258); 58 | this.ResumeLayout(false); 59 | 60 | } 61 | 62 | #endregion 63 | 64 | private System.Windows.Forms.ProgressBar pbMain; 65 | private System.Windows.Forms.RichTextBox rtLog; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/panels/Panel2.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/panels/Panel3.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace BetterDiscordWI.panels 2 | { 3 | partial class Panel3 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | components = new System.ComponentModel.Container(); 32 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 33 | } 34 | 35 | #endregion 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Installers/dotNet/BetterDiscordWI/panels/Panel3.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace BetterDiscordWI.panels 4 | { 5 | public partial class Panel3 : UserControl 6 | { 7 | public Panel3() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Installers/dotNet/README.md: -------------------------------------------------------------------------------- 1 | ## To Compile Move the DLL's folder to ``BetterDiscordWI\bin`` 2 | ## Enjoy Building the Installer. -------------------------------------------------------------------------------- /Installers/dotNet/config.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/dotNet/config.xml -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BetterDiscordWI", "BetterDiscordWI\BetterDiscordWI.csproj", "{390615F1-CE33-4173-9E8C-4E4F3EB1758D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {390615F1-CE33-4173-9E8C-4E4F3EB1758D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {390615F1-CE33-4173-9E8C-4E4F3EB1758D}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {390615F1-CE33-4173-9E8C-4E4F3EB1758D}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {390615F1-CE33-4173-9E8C-4E4F3EB1758D}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/FormMain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | using BetterDiscordWI.panels; 5 | 6 | namespace BetterDiscordWI { 7 | 8 | public partial class FormMain : Form { 9 | 10 | private readonly IPanel[] _panels = { new LicensePanel(), new ConfigPanel(), new InstallPanel() }; 11 | private int _currentPanel; 12 | 13 | public string DiscordPath = null; 14 | public bool RestartDiscord = true; 15 | public bool Stable = true, Canary, Ptb; 16 | 17 | public FormMain() { 18 | InitializeComponent(); 19 | 20 | foreach (var panel in _panels) { 21 | panel.SetForm(this); 22 | panel.Control.Dock = DockStyle.Fill; 23 | panelDock.Controls.Add(panel.Control); 24 | } 25 | SwitchPanel(0); 26 | } 27 | 28 | 29 | public void SetTitle(string title) => lblTitle.Text = title; 30 | 31 | public void SwitchPanel(int index) { 32 | _currentPanel = index; 33 | foreach (var panel in _panels) { panel.HidePanel(); } 34 | SetTitle($"BetterDiscord {_panels[index].Title}"); 35 | _panels[index].ShowPanel(); 36 | } 37 | 38 | private readonly Pen _borderPen = new Pen(Color.FromArgb(160, 160, 160)); 39 | protected override void OnPaint(PaintEventArgs e) { 40 | base.OnPaint(e); 41 | 42 | var g = e.Graphics; 43 | g.FillRectangle(SystemBrushes.Window, new Rectangle(0, 0, Width, 85)); 44 | g.DrawLine(_borderPen, 0, 85, Width, 85); 45 | g.DrawLine(SystemPens.Window, 0, 86, Width, 86); 46 | 47 | g.DrawLine(_borderPen, 0, 445, Width, 445); 48 | g.DrawLine(SystemPens.Window, 0, 446, Width, 446); 49 | } 50 | 51 | private void btnNext_Click(object sender, EventArgs e) { 52 | _currentPanel++; 53 | SwitchPanel(_currentPanel); 54 | } 55 | 56 | private void btnCancel_Click(object sender, EventArgs e) { 57 | Application.Exit(); 58 | } 59 | 60 | private void btnBack_Click(object sender, EventArgs e) { 61 | _currentPanel--; 62 | SwitchPanel(_currentPanel); 63 | } 64 | 65 | public void Fail() { 66 | btnCancel.ShowEnable(); 67 | btnNext.ShowDisable(); 68 | btnBack.ShowEnable(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace BetterDiscordWI { 8 | static class Program { 9 | /// 10 | /// The main entry point for the application. 11 | /// 12 | [STAThread] 13 | static void Main() { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault(false); 16 | Application.Run(new FormMain()); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("BetterDiscordWI")] 9 | [assembly: AssemblyDescription("BetterDiscord Windows Installer")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("CSharpForLife")] 12 | [assembly: AssemblyProduct("BetterDiscordWI")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("390615f1-ce33-4173-9e8c-4e4f3eb1758d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("0.3.0.0")] 36 | [assembly: AssemblyFileVersion("0.3.0.0")] 37 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace BetterDiscordWI.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BetterDiscordWI.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap Betterdiscord_small_black_blue { 67 | get { 68 | object obj = ResourceManager.GetObject("Betterdiscord_small_black_blue", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap Betterdiscord_small_white_blue { 77 | get { 78 | object obj = ResourceManager.GetObject("Betterdiscord_small_white_blue", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace BetterDiscordWI.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/Resources/Betterdiscord small black+blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/dotNet2/BetterDiscordWI/Resources/Betterdiscord small black+blue.png -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/Resources/Betterdiscord small white+blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/dotNet2/BetterDiscordWI/Resources/Betterdiscord small white+blue.png -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Threading.Tasks; 4 | 5 | namespace BetterDiscordWI { 6 | public static class Utils { 7 | 8 | public static WebHeaderCollection Headers = new WebHeaderCollection { ["User-Agent"] = "Mozilla/5.0" }; 9 | 10 | public static async Task GetHash() { 11 | using (var wc = new WebClient { Headers = Headers }) { 12 | var result = await wc.DownloadStringTaskAsync(@"https://api.github.com/repos/Jiiks/BetterDiscordApp/commits/master"); 13 | 14 | var start = result.IndexOf("{\"sha\":") + 8; 15 | var end = result.IndexOf("\",\"") - 8; 16 | 17 | return result.Substring(start, end); 18 | } 19 | } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/betterdiscord_small_white_blue_icO_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/Installers/dotNet2/BetterDiscordWI/betterdiscord_small_white_blue_icO_icon.ico -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/controls/Button.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace BetterDiscordWI.controls { 2 | partial class Button { 3 | /// 4 | /// Required designer variable. 5 | /// 6 | private System.ComponentModel.IContainer components = null; 7 | 8 | /// 9 | /// Clean up any resources being used. 10 | /// 11 | /// true if managed resources should be disposed; otherwise, false. 12 | protected override void Dispose(bool disposing) { 13 | if (disposing && (components != null)) { 14 | components.Dispose(); 15 | } 16 | base.Dispose(disposing); 17 | } 18 | 19 | #region Component Designer generated code 20 | 21 | /// 22 | /// Required method for Designer support - do not modify 23 | /// the contents of this method with the code editor. 24 | /// 25 | private void InitializeComponent() { 26 | components = new System.ComponentModel.Container(); 27 | } 28 | 29 | #endregion 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/controls/Button.cs: -------------------------------------------------------------------------------- 1 | namespace BetterDiscordWI.controls { 2 | public partial class Button : System.Windows.Forms.Button { 3 | public Button() { 4 | InitializeComponent(); 5 | } 6 | 7 | public Button HideDisable(string newText = null) { 8 | if (newText != null) Text = newText; 9 | Hide(); 10 | Enabled = false; 11 | return this; 12 | } 13 | 14 | public Button HideEnable(string newText = null) { 15 | if (newText != null) Text = newText; 16 | Hide(); 17 | Enabled = true; 18 | return this; 19 | } 20 | 21 | public Button ShowDisable(string newText = null) { 22 | if (newText != null) Text = newText; 23 | Show(); 24 | Enabled = false; 25 | return this; 26 | } 27 | 28 | public Button ShowEnable(string newText = null) { 29 | if (newText != null) Text = newText; 30 | Show(); 31 | Enabled = true; 32 | return this; 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/panels/ConfigPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text.RegularExpressions; 4 | using System.Windows.Forms; 5 | 6 | namespace BetterDiscordWI.panels { 7 | public partial class ConfigPanel : UserControl, IPanel { 8 | 9 | private FormMain _formMain; 10 | private readonly Regex _matcher = new Regex(@"[0-9]+\.[0-9]+\.[0-9]+"); 11 | 12 | private static string StablePath => $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\\Discord"; 13 | private static bool StableExists() => Directory.Exists(StablePath); 14 | private static string CanaryPath => $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\\DiscordCanary"; 15 | private static bool CanaryExists() => Directory.Exists(CanaryPath); 16 | private static string PtbPath => $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\\DiscordPTB"; 17 | private static bool PtbExists() => Directory.Exists(PtbPath); 18 | 19 | public ConfigPanel() { 20 | InitializeComponent(); 21 | } 22 | 23 | public void ShowPanel() { 24 | _formMain.btnBack.ShowEnable(); 25 | _formMain.btnCancel.ShowEnable(); 26 | _formMain.btnNext.ShowEnable("Install"); 27 | 28 | if (!CanaryExists()) { 29 | lblCanarywarning.Show(); 30 | cbCanary.Enabled = false; 31 | } 32 | 33 | if (!PtbExists()) { 34 | lblPtbwarning.Show(); 35 | cbPtb.Enabled = false; 36 | } 37 | 38 | if (!StableExists()) { 39 | lblStablewarning.Show(); 40 | cbStable.Enabled = false; 41 | } 42 | 43 | if (!StableExists() && !CanaryExists() && PtbExists()) { 44 | _formMain.btnNext.ShowDisable(); 45 | } 46 | 47 | cbRestart.Checked = _formMain.RestartDiscord; 48 | cbCanary.Checked = _formMain.Canary; 49 | cbPtb.Checked = _formMain.Ptb; 50 | cbStable.Checked = _formMain.Stable; 51 | 52 | LocateDiscord(); 53 | 54 | Show(); 55 | } 56 | 57 | public void HidePanel() { 58 | Hide(); 59 | } 60 | 61 | public void SetForm(FormMain formMain) => _formMain = formMain; 62 | 63 | public string Title => "Installation"; 64 | public UserControl Control => this; 65 | 66 | private void btnBrowse_Click(object sender, System.EventArgs e) { 67 | var fbd = new FolderBrowserDialog {SelectedPath = tbPath.Text}; 68 | fbd.ShowDialog(); 69 | 70 | tbPath.Text = fbd.SelectedPath; 71 | _formMain.DiscordPath = fbd.SelectedPath; 72 | } 73 | 74 | private void LocateDiscord() { 75 | var finalPath = GetLatestVersion(cbPtb.Checked ? PtbPath : cbCanary.Checked ? CanaryPath : StablePath); 76 | if (finalPath == string.Empty) finalPath = "Not found!"; 77 | 78 | tbPath.Text = finalPath; 79 | _formMain.DiscordPath = finalPath; 80 | _formMain.Stable = cbStable.Checked; 81 | _formMain.Canary = cbCanary.Checked; 82 | _formMain.Ptb = cbPtb.Checked; 83 | } 84 | 85 | 86 | 87 | private string GetLatestVersion(string path) { 88 | var dirs = Directory.GetDirectories(path); 89 | if (dirs.Length <= 0) return string.Empty; 90 | var latest = dirs[0]; 91 | 92 | foreach (var dir in dirs) { 93 | if (!_matcher.IsMatch(dir)) continue; 94 | if (string.CompareOrdinal(dir, latest) > 0) latest = dir; 95 | } 96 | 97 | return latest; 98 | } 99 | 100 | private void cbCanary_CheckedChanged(object sender, EventArgs e) { 101 | if (cbCanary.Checked) { 102 | cbPtb.Checked = false; 103 | cbStable.Checked = false; 104 | } 105 | LocateDiscord(); 106 | } 107 | 108 | private void cbPtb_CheckedChanged(object sender, EventArgs e) { 109 | if (cbPtb.Checked) { 110 | cbCanary.Checked = false; 111 | cbStable.Checked = false; 112 | } 113 | LocateDiscord(); 114 | } 115 | 116 | private void cbRestart_CheckedChanged(object sender, EventArgs e) { 117 | _formMain.RestartDiscord = cbRestart.Checked; 118 | } 119 | 120 | private void cbStable_CheckedChanged(object sender, EventArgs e) { 121 | if (cbStable.Checked) { 122 | cbCanary.Checked = false; 123 | cbPtb.Checked = false; 124 | } 125 | LocateDiscord(); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/panels/ConfigPanel.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/panels/IPanel.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace BetterDiscordWI.panels { 4 | internal interface IPanel { 5 | void ShowPanel(); 6 | void HidePanel(); 7 | void SetForm(FormMain formMain); 8 | string Title { get; } 9 | UserControl Control { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/panels/InstallPanel.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace BetterDiscordWI.panels { 2 | partial class InstallPanel { 3 | /// 4 | /// Required designer variable. 5 | /// 6 | private System.ComponentModel.IContainer components = null; 7 | 8 | /// 9 | /// Clean up any resources being used. 10 | /// 11 | /// true if managed resources should be disposed; otherwise, false. 12 | protected override void Dispose(bool disposing) { 13 | if (disposing && (components != null)) { 14 | components.Dispose(); 15 | } 16 | base.Dispose(disposing); 17 | } 18 | 19 | #region Component Designer generated code 20 | 21 | /// 22 | /// Required method for Designer support - do not modify 23 | /// the contents of this method with the code editor. 24 | /// 25 | private void InitializeComponent() { 26 | this.rtbStatus = new System.Windows.Forms.RichTextBox(); 27 | this.pbStatus = new System.Windows.Forms.ProgressBar(); 28 | this.cbDetailed = new System.Windows.Forms.CheckBox(); 29 | this.rtbDetailed = new System.Windows.Forms.RichTextBox(); 30 | this.SuspendLayout(); 31 | // 32 | // rtbStatus 33 | // 34 | this.rtbStatus.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 35 | | System.Windows.Forms.AnchorStyles.Left) 36 | | System.Windows.Forms.AnchorStyles.Right))); 37 | this.rtbStatus.Location = new System.Drawing.Point(3, 3); 38 | this.rtbStatus.Name = "rtbStatus"; 39 | this.rtbStatus.Size = new System.Drawing.Size(492, 126); 40 | this.rtbStatus.TabIndex = 0; 41 | this.rtbStatus.Text = ""; 42 | // 43 | // pbStatus 44 | // 45 | this.pbStatus.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 46 | | System.Windows.Forms.AnchorStyles.Right))); 47 | this.pbStatus.Location = new System.Drawing.Point(67, 135); 48 | this.pbStatus.Name = "pbStatus"; 49 | this.pbStatus.Size = new System.Drawing.Size(428, 23); 50 | this.pbStatus.TabIndex = 1; 51 | // 52 | // cbDetailed 53 | // 54 | this.cbDetailed.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 55 | this.cbDetailed.AutoSize = true; 56 | this.cbDetailed.Location = new System.Drawing.Point(4, 138); 57 | this.cbDetailed.Name = "cbDetailed"; 58 | this.cbDetailed.Size = new System.Drawing.Size(58, 17); 59 | this.cbDetailed.TabIndex = 2; 60 | this.cbDetailed.Text = "Details"; 61 | this.cbDetailed.UseVisualStyleBackColor = true; 62 | this.cbDetailed.CheckedChanged += new System.EventHandler(this.cbDetailed_CheckedChanged); 63 | // 64 | // rtbDetailed 65 | // 66 | this.rtbDetailed.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 67 | | System.Windows.Forms.AnchorStyles.Left) 68 | | System.Windows.Forms.AnchorStyles.Right))); 69 | this.rtbDetailed.Location = new System.Drawing.Point(3, 3); 70 | this.rtbDetailed.Name = "rtbDetailed"; 71 | this.rtbDetailed.Size = new System.Drawing.Size(492, 126); 72 | this.rtbDetailed.TabIndex = 3; 73 | this.rtbDetailed.Text = ""; 74 | this.rtbDetailed.Visible = false; 75 | // 76 | // InstallPanel 77 | // 78 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 79 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 80 | this.Controls.Add(this.rtbDetailed); 81 | this.Controls.Add(this.cbDetailed); 82 | this.Controls.Add(this.pbStatus); 83 | this.Controls.Add(this.rtbStatus); 84 | this.Name = "InstallPanel"; 85 | this.Size = new System.Drawing.Size(501, 166); 86 | this.ResumeLayout(false); 87 | this.PerformLayout(); 88 | 89 | } 90 | 91 | #endregion 92 | 93 | private System.Windows.Forms.RichTextBox rtbStatus; 94 | private System.Windows.Forms.ProgressBar pbStatus; 95 | private System.Windows.Forms.CheckBox cbDetailed; 96 | private System.Windows.Forms.RichTextBox rtbDetailed; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/panels/InstallPanel.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/panels/LicensePanel.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace BetterDiscordWI.panels { 2 | partial class LicensePanel { 3 | /// 4 | /// Required designer variable. 5 | /// 6 | private System.ComponentModel.IContainer components = null; 7 | 8 | /// 9 | /// Clean up any resources being used. 10 | /// 11 | /// true if managed resources should be disposed; otherwise, false. 12 | protected override void Dispose(bool disposing) { 13 | if (disposing && (components != null)) { 14 | components.Dispose(); 15 | } 16 | base.Dispose(disposing); 17 | } 18 | 19 | #region Component Designer generated code 20 | 21 | /// 22 | /// Required method for Designer support - do not modify 23 | /// the contents of this method with the code editor. 24 | /// 25 | private void InitializeComponent() { 26 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LicensePanel)); 27 | this.radioAccept = new System.Windows.Forms.RadioButton(); 28 | this.radioDecline = new System.Windows.Forms.RadioButton(); 29 | this.label1 = new System.Windows.Forms.Label(); 30 | this.richTextBox1 = new System.Windows.Forms.RichTextBox(); 31 | this.SuspendLayout(); 32 | // 33 | // radioAccept 34 | // 35 | this.radioAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 36 | this.radioAccept.AutoSize = true; 37 | this.radioAccept.Location = new System.Drawing.Point(413, 286); 38 | this.radioAccept.Name = "radioAccept"; 39 | this.radioAccept.Size = new System.Drawing.Size(59, 17); 40 | this.radioAccept.TabIndex = 0; 41 | this.radioAccept.Text = "Accept"; 42 | this.radioAccept.UseVisualStyleBackColor = true; 43 | // 44 | // radioDecline 45 | // 46 | this.radioDecline.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 47 | this.radioDecline.AutoSize = true; 48 | this.radioDecline.Checked = true; 49 | this.radioDecline.Location = new System.Drawing.Point(478, 286); 50 | this.radioDecline.Name = "radioDecline"; 51 | this.radioDecline.Size = new System.Drawing.Size(61, 17); 52 | this.radioDecline.TabIndex = 1; 53 | this.radioDecline.TabStop = true; 54 | this.radioDecline.Text = "Decline"; 55 | this.radioDecline.UseVisualStyleBackColor = true; 56 | // 57 | // label1 58 | // 59 | this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 60 | | System.Windows.Forms.AnchorStyles.Right))); 61 | this.label1.Location = new System.Drawing.Point(3, 5); 62 | this.label1.Name = "label1"; 63 | this.label1.Size = new System.Drawing.Size(480, 13); 64 | this.label1.TabIndex = 2; 65 | this.label1.Text = "Please read the following License Agreement and accept the terms before continuin" + 66 | "g the installation."; 67 | // 68 | // richTextBox1 69 | // 70 | this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 71 | | System.Windows.Forms.AnchorStyles.Left) 72 | | System.Windows.Forms.AnchorStyles.Right))); 73 | this.richTextBox1.Location = new System.Drawing.Point(3, 21); 74 | this.richTextBox1.Name = "richTextBox1"; 75 | this.richTextBox1.Size = new System.Drawing.Size(533, 259); 76 | this.richTextBox1.TabIndex = 3; 77 | this.richTextBox1.Text = resources.GetString("richTextBox1.Text"); 78 | // 79 | // LicensePanel 80 | // 81 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 82 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 83 | this.Controls.Add(this.richTextBox1); 84 | this.Controls.Add(this.label1); 85 | this.Controls.Add(this.radioDecline); 86 | this.Controls.Add(this.radioAccept); 87 | this.Name = "LicensePanel"; 88 | this.Size = new System.Drawing.Size(542, 306); 89 | this.ResumeLayout(false); 90 | this.PerformLayout(); 91 | 92 | } 93 | 94 | #endregion 95 | 96 | private System.Windows.Forms.RadioButton radioAccept; 97 | private System.Windows.Forms.RadioButton radioDecline; 98 | private System.Windows.Forms.Label label1; 99 | private System.Windows.Forms.RichTextBox richTextBox1; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Installers/dotNet2/BetterDiscordWI/panels/LicensePanel.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace BetterDiscordWI.panels { 4 | 5 | public partial class LicensePanel : UserControl, IPanel { 6 | 7 | private FormMain _formMain; 8 | 9 | public string Title => "License Agreement"; 10 | public UserControl Control => this; 11 | 12 | public LicensePanel() { 13 | InitializeComponent(); 14 | radioAccept.CheckedChanged += (sender, args) => { 15 | if (radioAccept.Checked) { 16 | _formMain.btnBack.HideDisable(); 17 | _formMain.btnNext.ShowEnable(); 18 | _formMain.btnCancel.ShowEnable(); 19 | return; 20 | } 21 | _formMain.btnBack.HideDisable(); 22 | _formMain.btnNext.ShowDisable(); 23 | _formMain.btnCancel.ShowEnable(); 24 | }; 25 | } 26 | 27 | public void SetForm(FormMain formMain) => _formMain = formMain; 28 | 29 | public void ShowPanel() { 30 | radioAccept.Checked = false; 31 | radioDecline.Checked = true; 32 | _formMain.btnBack.HideDisable(); 33 | _formMain.btnNext.ShowDisable(); 34 | _formMain.btnCancel.ShowEnable(); 35 | Show(); 36 | } 37 | 38 | public void HidePanel() => Hide(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015-present Jiiks | Jiiks.net 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Plugins/AutoPlayGifs.plugin.js: -------------------------------------------------------------------------------- 1 | //META{"name":"agif"}*// 2 | 3 | var agif = function () {}; 4 | 5 | // Autoplay GIFs 6 | agif.prototype.convert = function (target) { 7 | // Handle GIF 8 | $(target).find(".image:has(canvas)").each(function () { 9 | var image = $(this); 10 | var canvas = image.children("canvas").first(); 11 | // Replace GIF preview with actual image 12 | var src = canvas.attr("src"); 13 | if(src !== undefined) { 14 | image.replaceWith($("", { 15 | src: canvas.attr("src"), 16 | width: canvas.attr("width"), 17 | height: canvas.attr("height"), 18 | }).addClass("image kawaii-autogif")); 19 | } 20 | }); 21 | 22 | // Handle GIFV 23 | $(target).find(".embed-thumbnail-gifv:has(video)").each(function () { 24 | var embed = $(this); 25 | var video = embed.children("video").first(); 26 | // Remove the class, embed-thumbnail-gifv, to avoid the "GIF" overlay 27 | embed.removeClass("embed-thumbnail-gifv").addClass("kawaii-autogif"); 28 | // Prevent the default behavior of pausing the video 29 | embed.parent().on("mouseout.autoGif", function (event) { 30 | event.stopPropagation(); 31 | }); 32 | video[0].play(); 33 | }); 34 | }; 35 | 36 | agif.prototype.onMessage = function () {}; 37 | 38 | agif.prototype.onSwitch = function () {}; 39 | 40 | agif.prototype.start = function () { 41 | this.convert(document); 42 | }; 43 | 44 | agif.prototype.observer = function (e) { 45 | this.convert(e.target); 46 | }; 47 | 48 | agif.prototype.load = function () {}; 49 | agif.prototype.unload = function () {}; 50 | agif.prototype.stop = function () {}; 51 | agif.prototype.getSettingsPanel = function () { 52 | return ""; 53 | }; 54 | 55 | agif.prototype.getName = function () { 56 | return "Autogif"; 57 | }; 58 | agif.prototype.getDescription = function () { 59 | return "Autoplay gifs without having to hover."; 60 | }; 61 | agif.prototype.getVersion = function () { 62 | return "1.0.0"; 63 | }; 64 | agif.prototype.getAuthor = function () { 65 | return "noodlebox"; 66 | }; 67 | -------------------------------------------------------------------------------- /Plugins/CustomGame.plugin.js: -------------------------------------------------------------------------------- 1 | //META{"name":"customGamePlugin"}*// 2 | 3 | /* 4 | * #####################READ THIS!################################ 5 | * #####################READ THIS!################################ 6 | * 7 | * This plugin is discontinued and no longer works due to Discord having custom game title built in and is kept for archiving purposes only. 8 | * 9 | * #####################READ THIS!################################ 10 | * #####################READ THIS!################################ 11 | */ 12 | 13 | 14 | function customGamePlugin() {} 15 | 16 | customGamePlugin.prototype.load = function() { 17 | }; 18 | 19 | customGamePlugin.prototype.unload = function() { 20 | }; 21 | 22 | customGamePlugin.prototype.start = function() { 23 | return; 24 | var self = this; 25 | this.enabled = true; 26 | this.interval = setInterval(function() { 27 | self.setPlaying(); 28 | }, 60000); 29 | this.setPlaying(); 30 | }; 31 | 32 | customGamePlugin.prototype.stop = function() { 33 | return; 34 | var gp = this.game; 35 | this.game = ""; 36 | this.setPlaying(); 37 | this.game = gp; 38 | clearInterval(this.interval); 39 | this.enabled = false; 40 | }; 41 | 42 | customGamePlugin.prototype.getName = function() { 43 | return "Custom Game"; 44 | }; 45 | 46 | customGamePlugin.prototype.getDescription = function() { 47 | return "Set custom game as your playing status"; 48 | }; 49 | 50 | customGamePlugin.prototype.getVersion = function() { 51 | return "1.0"; 52 | }; 53 | 54 | customGamePlugin.prototype.getAuthor = function() { 55 | return "Jiiks"; 56 | }; 57 | 58 | customGamePlugin.prototype.getSettingsPanel = function() { 59 | if(this.game == null) this.game = ""; 60 | return ' ' + 61 | '' + 62 | ''; 63 | }; 64 | 65 | customGamePlugin.prototype.setGame = function(game) { 66 | if(game == null) { 67 | game = document.getElementById("cgPluginGame").value; 68 | } 69 | this.game = game; 70 | this.setPlaying(); 71 | }; 72 | 73 | customGamePlugin.prototype.setPlaying = function() { 74 | if(!this.enabled) return; 75 | if(this.uid == null) { 76 | if($(".account .avatar-small").css("background-image") == undefined)return; 77 | this.uid = $(".account .avatar-small").css("background-image").match(/\d+/); 78 | } 79 | 80 | if(this.game == null) this.game = ""; 81 | 82 | var minner = $('.channel-members .member[data-reactid*="'+this.uid+'"]').find(".member-inner") 83 | var mgame = minner.find(".member-game"); 84 | if(this.game != "") { 85 | if(mgame.length) { 86 | mgame.find("strong").text(this.game); 87 | } else { 88 | minner.append('
Playing: '+this.game+'
'); 89 | } 90 | } else { 91 | if(mgame.length) { 92 | mgame.remove(); 93 | } 94 | } 95 | 96 | BdApi.setPlaying(this.game); 97 | }; 98 | -------------------------------------------------------------------------------- /Plugins/GuildsScroller.plugin.js: -------------------------------------------------------------------------------- 1 | //META{"name":"GuildsScroller"}*// 2 | 3 | function GuildsScroller() {} 4 | 5 | GuildsScroller.prototype.load = function() { 6 | }; 7 | 8 | GuildsScroller.prototype.unload = function() { 9 | }; 10 | 11 | GuildsScroller.prototype.start = function() { 12 | $(".guilds").wrap('
').wrap('
'); 13 | }; 14 | GuildsScroller.prototype.stop = function() { 15 | $(".guilds").unwrap().unwrap(); 16 | }; 17 | 18 | GuildsScroller.prototype.update = function() { 19 | }; 20 | 21 | GuildsScroller.prototype.getName = function() { 22 | return "Guilds Scrollbar"; 23 | }; 24 | 25 | GuildsScroller.prototype.getDescription = function() { 26 | return "Adds a scrollbar to guilds/servers list"; 27 | }; 28 | 29 | GuildsScroller.prototype.getVersion = function() { 30 | return "1.0"; 31 | }; 32 | 33 | GuildsScroller.prototype.getAuthor = function() { 34 | return "Jiiks"; 35 | }; -------------------------------------------------------------------------------- /Plugins/clock.plugin.js: -------------------------------------------------------------------------------- 1 | //META{"name":"clockPlugin"}*// 2 | 3 | //Original clock code from http://cssdeck.com/labs/minimal-css3-digital-clock 4 | 5 | var clockPlugin = function () {}; 6 | 7 | clockPlugin.prototype.start = function () { 8 | BdApi.clearCSS("clockPluginCss"); 9 | BdApi.injectCSS("clockPluginCss", '#clockPluginClock { position:absolute; color:#FFF; background:#333333; padding:0 12px 0 13px; min-width:55px; max-width:55px; z-index:100; }'); 10 | var self = this; 11 | this.clock = $("
", { id: "clockPluginClock" }); 12 | $("body").append(this.clock); 13 | 14 | this.pad = function(x) { 15 | return x < 10 ? '0'+x : x; 16 | }; 17 | 18 | this.ticktock = function() { 19 | var d = new Date(); 20 | var h = self.pad(d.getHours()); 21 | var m = self.pad(d.getMinutes()); 22 | var s = self.pad(d.getSeconds()); 23 | var current_time = [h,m,s].join(':'); 24 | self.clock.html(current_time); 25 | }; 26 | 27 | this.ticktock12 = function() { 28 | var suffix = "AM"; 29 | var d = new Date(); 30 | var h = d.getHours(); 31 | var m = self.pad(d.getMinutes()); 32 | var s = self.pad(d.getSeconds()); 33 | 34 | if(h >= 12) { 35 | h -= 12; 36 | suffix = "PM"; 37 | } 38 | if(h == 0) { 39 | h = 12; 40 | } 41 | 42 | h = self.pad(h); 43 | 44 | var current_time = [h,m,s].join(":") + suffix; 45 | self.clock.html(current_time); 46 | }; 47 | 48 | this.ticktock(); 49 | this.interval = setInterval(this.ticktock, 1000); 50 | }; 51 | 52 | clockPlugin.prototype.load = function () { 53 | 54 | }; 55 | 56 | clockPlugin.prototype.unload = function () {} 57 | ; 58 | 59 | clockPlugin.prototype.stop = function () { 60 | BdApi.clearCSS("clockPluginCss"); 61 | clearInterval(this.interval); 62 | this.clock.remove(); 63 | }; 64 | 65 | clockPlugin.prototype.onMessage = function () { 66 | 67 | }; 68 | 69 | clockPlugin.prototype.onSwitch = function () { 70 | 71 | }; 72 | 73 | clockPlugin.prototype.observer = function (e) { 74 | 75 | }; 76 | 77 | clockPlugin.prototype.getSettingsPanel = function () { 78 | return ""; 79 | }; 80 | 81 | clockPlugin.prototype.getName = function () { 82 | return "Clock Plugin"; 83 | }; 84 | 85 | clockPlugin.prototype.getDescription = function () { 86 | return "Adds a clock to Discord"; 87 | }; 88 | 89 | clockPlugin.prototype.getVersion = function () { 90 | return "0.1.0"; 91 | }; 92 | 93 | clockPlugin.prototype.getAuthor = function () { 94 | return "Jiiks"; 95 | }; -------------------------------------------------------------------------------- /Plugins/customRoleColour.plugin.js: -------------------------------------------------------------------------------- 1 | //META{"name":"crr"}*// 2 | 3 | function crr() {} 4 | 5 | crr.prototype.start = function () { 6 | this.crrMt = new MutationObserver(function(mutations) { 7 | if($(".roles").length > 0) { 8 | if($("#ccpicker").length < 1) { 9 | 10 | var selectedRole = $(".roles").find("li.selected"); 11 | var roleId = selectedRole.data("reactid").split("$").slice(-1)[0]; 12 | var serverId = $(".guilds .active").data("reactid").split("$").slice(-1)[0]; 13 | var rgb = selectedRole.css("color").match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/); 14 | 15 | function hex(x) { 16 | return ("0" + parseInt(x).toString(16)).slice(-2); 17 | } 18 | var curColour = "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]); 19 | 20 | var picker = $("", { 21 | type: "color", 22 | class: "swatch default", 23 | id: "ccpicker" 24 | }); 25 | 26 | $(".color-picker .swatches").append(picker); 27 | picker.prop("value", curColour); 28 | 29 | picker.on("change", function() { 30 | 31 | var token = localStorage["token"].replace(/"/g, ""); 32 | var newColour = parseInt($(this).prop("value").slice(1), 16); 33 | $.ajax({ 34 | type: 'GET', 35 | url: 'https://discordapp.com/api/guilds/'+serverId+'/roles?token='+token, 36 | success: function(data) { 37 | for(var i = 0 ; i < data.length ; i++) { 38 | if(data[i]["id"] == roleId) { 39 | var request = new XMLHttpRequest(); 40 | request.open('PATCH', 'https://discordapp.com/api/guilds/'+serverId+'/roles/'+roleId+'?token='+localStorage["token"].replace(/"/g, ""), false); 41 | request.setRequestHeader("Content-type","application/json"); 42 | request.send('{"color": '+newColour+', "hoist": '+data[i]["hoist"]+', "name": "'+data[i]["name"]+'", "permissions": '+data[i]["permissions"]+'}'); 43 | break; 44 | } 45 | } 46 | } 47 | }); 48 | }); 49 | } 50 | } 51 | }); 52 | this.crrMt.observe(document, {childList:true, subtree:true}) 53 | }; 54 | crr.prototype.stop = function () { 55 | this.crrMt.disconnect(); 56 | }; 57 | 58 | crr.prototype.load = function () { 59 | //Called when plugin is loaded 60 | }; 61 | 62 | crr.prototype.unload = function () { 63 | //Called when plugin is unloaded 64 | }; 65 | 66 | crr.prototype.getName = function () { 67 | return "Custom Role Colours"; 68 | }; 69 | 70 | crr.prototype.getDescription = function () { 71 | return "Set custom role colours"; 72 | }; 73 | 74 | crr.prototype.getVersion = function () { 75 | return "1.0"; 76 | }; 77 | 78 | crr.prototype.getAuthor = function () { 79 | return "Jiiks, Pohky"; 80 | }; 81 | 82 | crr.prototype.getSettingsPanel = function () { 83 | return ''; 84 | }; -------------------------------------------------------------------------------- /Plugins/dblClickEdit.plugin.js: -------------------------------------------------------------------------------- 1 | //META{"name":"dblClickEdit"}*// 2 | 3 | var dblClickEdit = function () {}; 4 | 5 | dblClickEdit.prototype.handler = function(e) { 6 | const message = e.target.closest('[class^=messageCozy]') || e.target.closest('[class^=messageCompact]'); 7 | if (!message) return; 8 | const btn = message.querySelector('[class^=buttonContainer] [class^=button-]'); 9 | if (!btn) return; 10 | btn.click(); 11 | const popup = document.querySelector('[class^=container][role=menu]'); 12 | if (!popup) return; 13 | const rii = popup[Object.keys(popup).find(k => k.startsWith('__reactInternal'))]; 14 | if (!rii || !rii.memoizedProps || !rii.memoizedProps.children || !rii.memoizedProps.children[1] || !rii.memoizedProps.children[1].props || !rii.memoizedProps.children[1].props.onClick) return; 15 | rii.memoizedProps.children[1].props.onClick(); 16 | }; 17 | 18 | dblClickEdit.prototype.onMessage = function () { 19 | }; 20 | dblClickEdit.prototype.onSwitch = function () { 21 | }; 22 | dblClickEdit.prototype.start = function () { 23 | document.addEventListener('dblclick', this.handler); 24 | }; 25 | 26 | dblClickEdit.prototype.load = function () {}; 27 | dblClickEdit.prototype.unload = function () { 28 | document.removeEventListener('dblclick', this.handler); 29 | }; 30 | dblClickEdit.prototype.stop = function () { 31 | document.removeEventListener('dblclick', this.handler); 32 | }; 33 | dblClickEdit.prototype.getSettingsPanel = function () { 34 | return ""; 35 | }; 36 | 37 | dblClickEdit.prototype.getName = function () { 38 | return "Double click edit"; 39 | }; 40 | dblClickEdit.prototype.getDescription = function () { 41 | return "Double click messages to edit them"; 42 | }; 43 | dblClickEdit.prototype.getVersion = function () { 44 | return "0.2.1"; 45 | }; 46 | dblClickEdit.prototype.getAuthor = function () { 47 | return "Jiiks"; 48 | }; 49 | -------------------------------------------------------------------------------- /Plugins/emoteBlacklist.plugin.js: -------------------------------------------------------------------------------- 1 | //META{"name":"emoteBlacklist"}*// 2 | 3 | var emoteBlacklist = function () {}; 4 | 5 | emoteBlacklist.prototype.onMessage = function () { 6 | }; 7 | emoteBlacklist.prototype.onSwitch = function () { 8 | }; 9 | emoteBlacklist.prototype.start = function () { 10 | window.ebEnabled = true; 11 | var self = this; 12 | var em = bdPluginStorage.get("emoteBlacklist", "blacklist"); 13 | 14 | if(em === null) return; 15 | em.forEach(function(emote) { 16 | self.remove(emote); 17 | self.add(emote); 18 | }); 19 | }; 20 | emoteBlacklist.prototype.add = function(emote) { 21 | window.bemotes.push(emote); 22 | }; 23 | emoteBlacklist.prototype.remove = function(emote) { 24 | var index = bemotes.indexOf(emote); 25 | if(index > -1) { 26 | window.bemotes.splice(index, 1); 27 | } 28 | } 29 | 30 | emoteBlacklist.prototype.load = function () {}; 31 | emoteBlacklist.prototype.unload = function () { 32 | }; 33 | emoteBlacklist.prototype.stop = function () { 34 | window.ebEnabled = false; 35 | this.clear(); 36 | }; 37 | emoteBlacklist.prototype.clear = function() { 38 | var self = this; 39 | var em = bdPluginStorage.get("emoteBlacklist", "blacklist"); 40 | if(em === null) return; 41 | em.forEach(function(emote) { 42 | self.remove(emote); 43 | }); 44 | }; 45 | emoteBlacklist.prototype.getSettingsPanel = function () { 46 | var em = bdPluginStorage.get("emoteBlacklist", "blacklist"); 47 | 48 | var html = ''; 49 | html += '

Emote Blacklist'; 50 | html += ''; 57 | html += ''; 58 | html += 'Add emote names here to blacklist(1 per line)'; 59 | return html; 60 | }; 61 | emoteBlacklist.prototype.save = function() { 62 | this.clear(); 63 | var blist = []; 64 | $("#emoteBlistTa").val().split("\n").forEach(function(item) { 65 | blist.push(item); 66 | }); 67 | bdPluginStorage.set("emoteBlacklist", "blacklist", blist); 68 | if(window.ebEnabled) { 69 | this.start(); 70 | } 71 | }; 72 | 73 | emoteBlacklist.prototype.getName = function () { 74 | return "Emote Blacklist"; 75 | }; 76 | emoteBlacklist.prototype.getDescription = function () { 77 | return "Blacklist emotes locally"; 78 | }; 79 | emoteBlacklist.prototype.getVersion = function () { 80 | return "0.1.0"; 81 | }; 82 | emoteBlacklist.prototype.getAuthor = function () { 83 | return "Jiiks"; 84 | }; -------------------------------------------------------------------------------- /Plugins/mediaSupport.plugin.js: -------------------------------------------------------------------------------- 1 | //META{"name":"mediaSupport"}*// 2 | 3 | var mediaSupport = function () {}; 4 | 5 | mediaSupport.prototype.convert = function () { 6 | $(".message a").each(function() { 7 | var t = $(this); 8 | var href = t.attr("href"); 9 | if(href == undefined) return true; 10 | href = href.replace("http:", "https:"); 11 | if(!href.endsWith(".mp4") && !href.endsWith(".webm") && !href.endsWith(".ogg") && !href.endsWith(".mp3") && !href.endsWith(".wav")) return true; 12 | var video = true; 13 | var type = "webm"; 14 | if(href.endsWith(".mp4")) type = "mp4"; 15 | if(href.endsWith(".ogg")) type = "ogg"; 16 | if(href.endsWith(".mp3")) { 17 | type = "mpeg"; 18 | video = false; 19 | } 20 | if(href.endsWith(".wav")) { 21 | type = "wav"; 22 | video = false; 23 | } 24 | 25 | if(video) { 26 | t.replaceWith(''); 27 | } else { 28 | t.replaceWith(''); 29 | } 30 | }); 31 | }; 32 | 33 | mediaSupport.prototype.onMessage = function () { 34 | setTimeout(this.convert(), 2000); 35 | }; 36 | mediaSupport.prototype.onSwitch = function () { 37 | this.convert(); 38 | }; 39 | mediaSupport.prototype.start = function () { 40 | this.convert(); 41 | }; 42 | 43 | mediaSupport.prototype.load = function () {}; 44 | mediaSupport.prototype.unload = function () {}; 45 | mediaSupport.prototype.stop = function () {}; 46 | mediaSupport.prototype.getSettingsPanel = function () { 47 | return ""; 48 | }; 49 | 50 | mediaSupport.prototype.getName = function () { 51 | return "Media Support"; 52 | }; 53 | mediaSupport.prototype.getDescription = function () { 54 | return "Add support for html5 media"; 55 | }; 56 | mediaSupport.prototype.getVersion = function () { 57 | return "0.1.0"; 58 | }; 59 | mediaSupport.prototype.getAuthor = function () { 60 | return "Jiiks"; 61 | }; -------------------------------------------------------------------------------- /Plugins/properTimestamps.plugin.js: -------------------------------------------------------------------------------- 1 | //META{"name":"properTimestamps"}*// 2 | 3 | var properTimestamps = function () {}; 4 | 5 | properTimestamps.prototype.convert = function () { 6 | $(".timestamp").each(function() { 7 | var t = $(this); 8 | 9 | if(t.data("24") != undefined) return; 10 | 11 | var text = t.text(); 12 | var matches = /(.*)?at\s+(\d{1,2}):(\d{1,2})\s+(.*)/.exec(text); 13 | if(matches == null) return false; 14 | if(matches.length < 5) return false; 15 | 16 | var h = parseInt(matches[2]); 17 | if(matches[4] == "AM") { 18 | if(h == 12) h -= 12; 19 | }else if(matches[4] == "PM") { 20 | if(h < 12) h += 12; 21 | } 22 | 23 | matches[2] = ('0' + h).slice(-2); 24 | t.text(matches[1] + matches[2] + ":" + matches[3]); 25 | t.data("24", true); 26 | }); 27 | }; 28 | 29 | properTimestamps.prototype.onMessage = function () { 30 | this.convert(); 31 | }; 32 | properTimestamps.prototype.onSwitch = function () { 33 | this.convert(); 34 | }; 35 | properTimestamps.prototype.start = function () { 36 | this.convert(); 37 | }; 38 | 39 | properTimestamps.prototype.load = function () {}; 40 | properTimestamps.prototype.unload = function () {}; 41 | properTimestamps.prototype.stop = function () {}; 42 | properTimestamps.prototype.getSettingsPanel = function () { 43 | return ""; 44 | }; 45 | 46 | properTimestamps.prototype.getName = function () { 47 | return "Proper Timestamps"; 48 | }; 49 | properTimestamps.prototype.getDescription = function () { 50 | return "24 hours timestamps"; 51 | }; 52 | properTimestamps.prototype.getVersion = function () { 53 | return "0.1.0"; 54 | }; 55 | properTimestamps.prototype.getAuthor = function () { 56 | return "Jiiks"; 57 | }; -------------------------------------------------------------------------------- /Plugins/typingsound.plugin.js: -------------------------------------------------------------------------------- 1 | //META{"name":"typingSoundPlugin"}*// 2 | 3 | function typingSoundPlugin() {} 4 | 5 | typingSoundPlugin.prototype.load = function() { 6 | if($("#tsp-ts").length) return; 7 | $("head").append(''); 8 | this.ts = $("#tsp-ts"); 9 | if($("#tsp-bs").length) return; 10 | $("head").append(''); 11 | this.bs = $("#tsp-bs"); 12 | }; 13 | 14 | typingSoundPlugin.prototype.unload = function() { 15 | $("#tsp-ts").remove(); 16 | $("#tsp-bs").remove(); 17 | }; 18 | 19 | typingSoundPlugin.prototype.start = function() { 20 | var self = this; 21 | $(document).on("keypress.ts", function(e) { 22 | self.ts.trigger("pause"); 23 | self.bs.trigger("pause"); 24 | self.ts.prop("currentTime", 0); 25 | self.bs.prop("currentTime", 0); 26 | self.ts.trigger("play"); 27 | }); 28 | 29 | $(document).on("keydown.ts", function(e) { 30 | if(e.keyCode == 8) { 31 | self.bs.trigger("pause"); 32 | self.bs.prop("currentTime", 0); 33 | self.bs.trigger("play"); 34 | return; 35 | } 36 | }); 37 | }; 38 | 39 | typingSoundPlugin.prototype.stop = function() { 40 | $(document).off("keypress.ts"); 41 | $(document).off("keydown.ts"); 42 | }; 43 | 44 | typingSoundPlugin.prototype.getName = function() { 45 | return "Osu Sounds for Rai"; 46 | }; 47 | 48 | typingSoundPlugin.prototype.getDescription = function() { 49 | return "Plays Osu chat sounds when you type, can be used to play any sounds."; 50 | }; 51 | 52 | typingSoundPlugin.prototype.getVersion = function() { 53 | return "1.0"; 54 | }; 55 | 56 | typingSoundPlugin.prototype.getAuthor = function() { 57 | return "Jiiks"; 58 | }; 59 | 60 | typingSoundPlugin.prototype.getSettingsPanel = function() { 61 | return ""; 62 | }; 63 | 64 | -------------------------------------------------------------------------------- /Plugins/videoSupport.js: -------------------------------------------------------------------------------- 1 | Superseded by Media Support: https://github.com/Jiiks/BetterDiscordApp/blob/master/Plugins/mediaSupport.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Note that this whole branch is deprecated. all further development is going on here: https://github.com/JsSucks/BetterDiscordApp 2 | 3 | # BetterDiscordApp 4 | 5 | # If you have issues then join the BD Discord server: [Here](https://discord.gg/0Tmfo5ZbORCRqbAd) 6 | 7 | # Do not contact Discord support about BD issues. 8 | 9 | ## All plugins must be named `*.plugin.js` and all themes must be named `*.theme.css` 10 | 11 | Better Discord App enhances the Discord desktop app with new features. 12 | 13 | ![ss](http://i.imgur.com/Gj6oD7z.png) 14 | 15 | ## Windows Universal Installer 16 | * Download the latest installer from [releases](https://github.com/Jiiks/BetterDiscordApp/releases) 17 | * Follow the instructions 18 | * .NET 4.0 required https://www.microsoft.com/en-us/download/details.aspx?id=30653 19 | * Windows Installer users asar.net https://github.com/Jiiks/asar.net 20 | 21 | ## Auto Installation 22 | * Download the latest package from [releases](https://github.com/Jiiks/BetterDiscordApp/releases) 23 | * Run the installer 24 | * Installer requires [node](https://nodejs.org/en/download/) download the binaries and place in the same folder as the installer if you don't have node installed. 25 | * Installer uses [asar](https://github.com/atom/asar) which is bundled with the installer. 26 | * Installer uses [wrench](https://github.com/ryanmcgrath/wrench-js) which is bundled with the installer. 27 | 28 | ## Manual Installation 29 | * Extract app.asar 30 | * Add BetterDiscord as a dependency 31 | * Add init to Discord load event 32 | * Move BetterDiscord to node_modules 33 | 34 | ## Features 35 | 36 | **Emotes:** 37 | BetterDiscord adds all [Twitch.tv](http://twitch.tv), most [FrankerFaceZ](http://frankerfacez.com) and [BetterTTV](http://betterttv.net) emotes to Discord. Supported emotes: https://betterdiscord.net/emotes 38 | 39 | **Quick Emote Menu:** 40 | Quick Emote Menu adds a menu for quickly adding twitch emotes and your favorite emotes. 41 | 42 | **Emote Autocapitalize:** 43 | Automatically capitalize [Twitch.tv](http://twitch.tv) global emotes. 44 | 45 | **Emote Autocomplete:** 46 | Automatically completes/suggests emotes.(soon) 47 | 48 | **Minimal Mode:** 49 | Minimal mode makes elements smaller and hides certain elements. 50 | 51 | **Voice Chat Mode:** 52 | Only display voice channels 53 | 54 | **Public Servers:** 55 | Public server listing provided by: [DiscordServers.com](https://www.discordservers.com/) 56 | ![ss](http://i.imgur.com/BVUZlu9.png) 57 | 58 | **Custom CSS** 59 | BetterDiscord supports custom CSS for styling Discord to your liking. 60 | 61 | **Custom Themes** 62 | BetterDiscord comes with a theme loader for loading your own or downloading themes made by others. 63 | 64 | **Plugins** 65 | BetterDiscord comes with a JavaScript plugin loader for loading your own or downloading plugins made by others. 66 | 67 | **Spoilers** 68 | Add spoilers to your chat, simply add [!s] to your message. 69 | 70 | **Save Logs Locally:** 71 | Save chatlogs locally.(soon) 72 | 73 | ## Adding your server to public servers 74 | As of JS1.60 the public server list is supplied by [DiscordServers.com](https://www.discordservers.com/) 75 | Add your server there and it will appear in the list! 76 | 77 | ## BetterDiscord Uses the following API's 78 | * https://twitchemotes.com/apidocs for Twitch emotes 79 | * https://api.betterttv.net/emotes for [BetterTTV](https://nightdev.com/betterttv/) emotes 80 | 81 | ## Credits 82 | * MacOS Installer by [Candunc](https://github.com/Candunc) 83 | * Emote titles by [pendo324](https://github.com/pendo324) 84 | * Majority of FFZ emote work by [Pohky](https://github.com/pohky) and [DeathStrikeV](https://github.com/DeathStrikeV) 85 | * Majority of BTTV emote work by [EhsanKia](https://github.com/EhsanKia) 86 | 87 | ## License 88 | 89 | The MIT License (MIT) 90 | 91 | Copyright (c) 2015-present Jiiks | [Jiiks.net](https://jiiks.net) 92 | 93 | Permission is hereby granted, free of charge, to any person obtaining a copy 94 | of this software and associated documentation files (the "Software"), to deal 95 | in the Software without restriction, including without limitation the rights 96 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 97 | copies of the Software, and to permit persons to whom the Software is 98 | furnished to do so, subject to the following conditions: 99 | 100 | The above copyright notice and this permission notice shall be included in 101 | all copies or substantial portions of the Software. 102 | 103 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 104 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 105 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 106 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 107 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 108 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 109 | THE SOFTWARE. 110 | -------------------------------------------------------------------------------- /betterdiscord.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/BetterDiscord'); 2 | -------------------------------------------------------------------------------- /data/emotefilter.json: -------------------------------------------------------------------------------- 1 | { 2 | "blacklist": [ 3 | "8Bit", 4 | "AAAAAH", 5 | "Abaddon", 6 | "Abra", 7 | "Advice", 8 | "Affe", 9 | "Ahaha", 10 | "Akame", 11 | "Akeno", 12 | "Akuma", 13 | "Alexis", 14 | "Amazing!", 15 | "Apollo", 16 | "Ares", 17 | "Arma3", 18 | "Armos", 19 | "Awww", 20 | "Awww", 21 | "Ayaya", 22 | "AyyLmao", 23 | "B1nzy", 24 | "Baby", 25 | "BabyRoll", 26 | "Bagels", 27 | "Ballin", 28 | "Barracks", 29 | "Beer", 30 | "Bella", 31 | "Benson", 32 | "Bepis", 33 | "Berge", 34 | "Besen", 35 | "BetterDiscord", 36 | "Boeuf", 37 | "Bomb", 38 | "Brille", 39 | "Brofist", 40 | "Bruh", 41 | "Bryce", 42 | "Bubs", 43 | "Bustin", 44 | "Cannon", 45 | "Challenge", 46 | "Charizard", 47 | "Charlotte", 48 | "Cheese", 49 | "chemo", 50 | "Chocobo", 51 | "COAST", 52 | "Coldsteel", 53 | "Cookie", 54 | "Crossover", 55 | "CSS3", 56 | "Cupid", 57 | "Dante", 58 | "Dayum", 59 | "Dedede", 60 | "DENIAL", 61 | "DESU", 62 | "Deud", 63 | "Dirk", 64 | "Dood", 65 | "double", 66 | "Dunked", 67 | "Dunno", 68 | "Eggman", 69 | "Elementals", 70 | "elgato", 71 | "emote", 72 | "Eugh", 73 | "Everyone!", 74 | "Excalibur", 75 | "Eyyy", 76 | "Eyyyyyy", 77 | "Ezreal", 78 | "Face", 79 | "facepalm", 80 | "FAIL", 81 | "FEESH", 82 | "Fennec", 83 | "Feuer", 84 | "FFXV", 85 | "Fighting", 86 | "Forman", 87 | "Freddie", 88 | "Gaben", 89 | "GAME!", 90 | "Gandalf", 91 | "Gazorpazorpfield", 92 | "Gengar", 93 | "George!", 94 | "GET!", 95 | "Goat", 96 | "Gosu", 97 | "Gramps", 98 | "Greninja", 99 | "Gunther", 100 | "H3H3", 101 | "HAAA", 102 | "HAHAHA", 103 | "Hai!", 104 | "Halp", 105 | "Hanzo", 106 | "Happy", 107 | "Harambe", 108 | "Hartz", 109 | "hasOwnProperty", 110 | "heartless", 111 | "HELLO!", 112 | "Hello", 113 | "Herz", 114 | "HEY!", 115 | "Hey!", 116 | "Heya!", 117 | "Hiho", 118 | "Hina", 119 | "Hobbes", 120 | "Huehue", 121 | "Humm", 122 | "Ibuki", 123 | "Ichigo", 124 | "inverse", 125 | "Isis", 126 | "Jabba", 127 | "Jace", 128 | "Jaffa", 129 | "Jago", 130 | "Josuke", 131 | "Kaede", 132 | "KAPPA", 133 | "Katze", 134 | "Kevin", 135 | "Kill", 136 | "Kirby", 137 | "Kitsune", 138 | "Kitsunemimi", 139 | "Kkkkk", 140 | "Koba", 141 | "Kona", 142 | "Koopa", 143 | "Lapras", 144 | "Lars", 145 | "Launch", 146 | "Leffen", 147 | "Lenny", 148 | "LetsPlay", 149 | "Licky", 150 | "Limpa", 151 | "Lonk", 152 | "Loool", 153 | "Lose", 154 | "Lotus", 155 | "Lucarionite", 156 | "Lulu", 157 | "Lunch", 158 | "Lunk", 159 | "Machine", 160 | "Mackey", 161 | "Magikarp", 162 | "MainMenu", 163 | "Matty", 164 | "Memelord", 165 | "Meow", 166 | "MERICA", 167 | "Mettaton", 168 | "Mhmm", 169 | "Midna", 170 | "Minecraft", 171 | "Minigames", 172 | "Miura", 173 | "Mmmm", 174 | "MMMMM", 175 | "Moddb", 176 | "Moin", 177 | "Moomin", 178 | "Morreu", 179 | "MSPaint", 180 | "Nati", 181 | "Nebby", 182 | "Nein", 183 | "Nimbus", 184 | "Nono", 185 | "Nooo", 186 | "NOOOO", 187 | "Noot", 188 | "Nuuu", 189 | "OBJECTION", 190 | "OHNO", 191 | "Ohok", 192 | "Okie", 193 | "OMG!", 194 | "OMGG", 195 | "OMGGG", 196 | "OneShot", 197 | "OPieOP", 198 | "osu!", 199 | "Overlord", 200 | "OVERWATCH", 201 | "Pachimari", 202 | "Panzer", 203 | "Parappa", 204 | "Peach", 205 | "penta", 206 | "Pera", 207 | "PERFECT", 208 | "Pfft", 209 | "Pikachu", 210 | "Pineapple", 211 | "Pinto", 212 | "PLAYS", 213 | "Pleure", 214 | "PokeBall", 215 | "Pokeball", 216 | "Pomeranian", 217 | "Poopy", 218 | "Poppins", 219 | "Poyo", 220 | "Profi", 221 | "Quack", 222 | "quadra", 223 | "RAGE", 224 | "Ravage", 225 | "Reblochon", 226 | "Rein", 227 | "REKTangle", 228 | "Rengar", 229 | "Resetti", 230 | "Ribombee", 231 | "Riolu", 232 | "Ripperoni", 233 | "RNGesus", 234 | "Roshan", 235 | "Rucksack", 236 | "Runescape", 237 | "Sammich", 238 | "Samus", 239 | "Schaf", 240 | "Sectoid", 241 | "Seriously", 242 | "Serperior", 243 | "Servine", 244 | "Shaymin", 245 | "Shirase", 246 | "Shitpost", 247 | "Shoryuken", 248 | "Shulk", 249 | "Slapstick", 250 | "SLEEPY", 251 | "Slowbro", 252 | "Smithing", 253 | "SMOL", 254 | "snap", 255 | "Snek", 256 | "Sniped", 257 | "Snivy", 258 | "Snorlax", 259 | "Soraka", 260 | "Spaghetti", 261 | "Spla2n", 262 | "SPONGEBOB", 263 | "Spongebob", 264 | "Spooky", 265 | "SRS!", 266 | "Stalin", 267 | "STEAK", 268 | "Sylveon", 269 | "Technical", 270 | "Thor", 271 | "Thump", 272 | "Toad", 273 | "Toejam", 274 | "Topkek", 275 | "Tower", 276 | "Tr4sh", 277 | "Trekt", 278 | "triple", 279 | "Twink", 280 | "Tyrael", 281 | "Uhhh", 282 | "Ulgrim", 283 | "Vayne", 284 | "vogel", 285 | "Voli", 286 | "WAOW", 287 | "Warwick", 288 | "Wassup", 289 | "Watching", 290 | "Whaaa", 291 | "Whalecum", 292 | "Whaaaat", 293 | "WHAT!", 294 | "Whoa!", 295 | "Woooh", 296 | "Wurst", 297 | "xDDDD", 298 | "Yay!", 299 | "YES!", 300 | "Yosh", 301 | "You!", 302 | "YouTube", 303 | "YOUTUBE", 304 | "Yup!", 305 | "Zangief", 306 | "Zerker", 307 | "Ziggs", 308 | "Zilean", 309 | "Zorua", 310 | "Zyra" 311 | ] 312 | } 313 | -------------------------------------------------------------------------------- /data/serverlist.json: -------------------------------------------------------------------------------- 1 | { "servers": { } } -------------------------------------------------------------------------------- /data/updater.json: -------------------------------------------------------------------------------- 1 | { 2 | "LatestVersion":"0.2.7", 3 | "CDN":"cdn.rawgit.com" 4 | } -------------------------------------------------------------------------------- /dev/css/CodeMirror.css: -------------------------------------------------------------------------------- 1 | /*CODEMIRROR*/ 2 | .CodeMirror{font-family:monospace;height:300px;color:#000;background-color:#EBEBEB !important;}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:30px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;margin-bottom:-30px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:none!important;-webkit-user-select:none;-moz-user-select:none;user-select:none}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-code{outline:0}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected,.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:0 0} 3 | 4 | .cm-s-neat span.cm-comment{color:#a86}.cm-s-neat span.cm-keyword{line-height:1em;font-weight:700;color:#00f}.cm-s-neat span.cm-string{color:#a22}.cm-s-neat span.cm-builtin{line-height:1em;font-weight:700;color:#077}.cm-s-neat span.cm-special{line-height:1em;font-weight:700;color:#0aa}.cm-s-neat span.cm-variable{color:#000}.cm-s-neat span.cm-atom,.cm-s-neat span.cm-number{color:#3a3}.cm-s-neat span.cm-meta{color:#555}.cm-s-neat span.cm-link{color:#3a3}.cm-s-neat .CodeMirror-activeline-background{background:#e8f2ff}.cm-s-neat .CodeMirror-matchingbracket{outline:grey solid 1px;color:#000!important} -------------------------------------------------------------------------------- /dev/js/00settings.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/dev/js/00settings.js -------------------------------------------------------------------------------- /dev/js/05customCssEditor.js: -------------------------------------------------------------------------------- 1 | function CustomCssEditor() { } 2 | 3 | CustomCssEditor.prototype.init = function() { 4 | var self = this; 5 | self.hideBackdrop = false; 6 | self.editor = CodeMirror.fromTextArea(document.getElementById("bd-custom-css-ta"), { 7 | lineNumbers: true, 8 | mode: 'css', 9 | indentUnit: 4, 10 | theme: 'neat' 11 | }); 12 | 13 | self.editor.on("change", function (cm) { 14 | var css = cm.getValue(); 15 | self.applyCustomCss(css, false, false); 16 | }); 17 | 18 | var attachEditor=""; 19 | attachEditor += "
"; 20 | attachEditor += "
    "; 21 | attachEditor += "
  • "; 22 | attachEditor += "
    "; 23 | attachEditor += "
    <\/span><\/div>"; 24 | attachEditor += " Live Update<\/span>"; 25 | attachEditor += " <\/div>"; 26 | attachEditor += " <\/li>"; 27 | attachEditor += "
  • "; 28 | attachEditor += "
    "; 29 | attachEditor += "
    <\/span><\/div>"; 30 | attachEditor += " Autosave<\/span>"; 31 | attachEditor += " <\/div>"; 32 | attachEditor += " <\/li>"; 33 | attachEditor += "
  • "; 34 | attachEditor += "
    "; 35 | attachEditor += "
    <\/span><\/div>"; 36 | attachEditor += " Hide Backdrop<\/span>"; 37 | attachEditor += " <\/div>"; 38 | attachEditor += " <\/li>"; 39 | attachEditor += " <\/ul>"; 40 | attachEditor += "
    "; 41 | attachEditor += " "; 44 | attachEditor += " <\/div>"; 45 | attachEditor += "<\/div>"; 46 | 47 | this.attachEditor = attachEditor; 48 | 49 | $("#bd-customcss-innerpane").append(attachEditor); 50 | 51 | $("#bd-customcss-detached-update").on("click", function() { 52 | self.applyCustomCss(self.editor.getValue(), true, false); 53 | return false; 54 | }); 55 | $("#bd-customcss-detached-save").on("click", function() { 56 | self.applyCustomCss(self.editor.getValue(), false, true); 57 | return false; 58 | }); 59 | 60 | 61 | var detachEditor=""; 62 | detachEditor += "
    "; 63 | detachEditor += "
    "; 64 | detachEditor += " <\/div>"; 65 | detachEditor += "<\/div>"; 66 | this.detachedEditor = detachEditor; 67 | }; 68 | 69 | CustomCssEditor.prototype.attach = function() { 70 | $("#editor-detached").hide(); 71 | $("#app-mount").removeClass("bd-detached-editor"); 72 | $("#bd-customcss-pane").append($("#bd-customcss-innerpane")); 73 | $("#bd-customcss-detached-detach").show(); 74 | $("#bd-customcss-detach-container").remove(); 75 | }; 76 | 77 | CustomCssEditor.prototype.detach = function() { 78 | var self = this; 79 | this.attach(); 80 | $("#editor-detached").show(); 81 | $("#bd-customcss-detached-detach").hide(); 82 | $("#app-mount").addClass("bd-detached-editor"); 83 | $(".app").parent().append(this.detachedEditor); 84 | $("#bd-customcss-detach-editor").append($("#bd-customcss-innerpane")); 85 | }; 86 | 87 | CustomCssEditor.prototype.applyCustomCss = function (css, forceupdate, forcesave) { 88 | if ($("#customcss").length == 0) { 89 | $("head").append(''); 90 | } 91 | 92 | if(forceupdate || settingsCookie["bda-css-0"]) { 93 | $("#customcss").html(css); 94 | } 95 | 96 | if(forcesave || settingsCookie["bda-css-1"]) { 97 | localStorage.setItem("bdcustomcss", btoa(css)); 98 | } 99 | }; -------------------------------------------------------------------------------- /dev/js/08voiceMode.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp VoiceMode JavaScript 2 | * Version: 1.0 3 | * Author: Jiiks | http://jiiks.net 4 | * Date: 25/10/2015 - 19:10 5 | * https://github.com/Jiiks/BetterDiscordApp 6 | */ 7 | 8 | function VoiceMode() { 9 | 10 | } 11 | 12 | VoiceMode.prototype.obsCallback = function () { 13 | var self = this; 14 | if (settingsCookie["bda-gs-4"]) { 15 | self.disable(); 16 | setTimeout(function () { 17 | self.enable(); 18 | }, 300); 19 | } 20 | }; 21 | 22 | VoiceMode.prototype.enable = function () { 23 | $(".scroller.guild-channels ul").first().css("display", "none"); 24 | $(".scroller.guild-channels header").first().css("display", "none"); 25 | $(".app.flex-vertical").first().css("overflow", "hidden"); 26 | $(".chat.flex-vertical.flex-spacer").first().css("visibility", "hidden").css("min-width", "0px"); 27 | $(".flex-vertical.channels-wrap").first().css("flex-grow", "100000"); 28 | $(".guild-header .btn.btn-hamburger").first().css("visibility", "hidden"); 29 | }; 30 | 31 | VoiceMode.prototype.disable = function () { 32 | $(".scroller.guild-channels ul").first().css("display", ""); 33 | $(".scroller.guild-channels header").first().css("display", ""); 34 | $(".app.flex-vertical").first().css("overflow", ""); 35 | $(".chat.flex-vertical.flex-spacer").first().css("visibility", "").css("min-width", ""); 36 | $(".flex-vertical.channels-wrap").first().css("flex-grow", ""); 37 | $(".guild-header .btn.btn-hamburger").first().css("visibility", ""); 38 | }; -------------------------------------------------------------------------------- /dev/js/09pluginModule.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp PluginModule JavaScript 2 | * Version: 1.0 3 | * Author: Jiiks | http://jiiks.net 4 | * Date: 16/12/2015 5 | * https://github.com/Jiiks/BetterDiscordApp 6 | */ 7 | 8 | var pluginCookie = {}; 9 | 10 | function PluginModule() { 11 | 12 | } 13 | 14 | PluginModule.prototype.loadPlugins = function () { 15 | 16 | this.loadPluginData(); 17 | 18 | $.each(bdplugins, function () { 19 | var plugin = this["plugin"]; 20 | plugin.load(); 21 | 22 | var name = plugin.getName(); 23 | var enabled = false; 24 | 25 | if (pluginCookie.hasOwnProperty(name)) { 26 | enabled = pluginCookie[name]; 27 | } else { 28 | pluginCookie[name] = false; 29 | } 30 | 31 | if (enabled) { 32 | plugin.start(); 33 | } 34 | }); 35 | }; 36 | 37 | PluginModule.prototype.handlePlugin = function (checkbox) { 38 | 39 | var cb = $(checkbox).children().find('input[type="checkbox"]'); 40 | var enabled = !cb.is(":checked"); 41 | var id = cb.attr("id").replace("__", " "); 42 | cb.prop("checked", enabled); 43 | 44 | if (enabled) { 45 | bdplugins[id]["plugin"].start(); 46 | pluginCookie[id] = true; 47 | } else { 48 | bdplugins[id]["plugin"].stop(); 49 | pluginCookie[id] = false; 50 | } 51 | 52 | this.savePluginData(); 53 | }; 54 | 55 | PluginModule.prototype.showSettings = function (plugin) { 56 | if (bdplugins[plugin] != null) { 57 | if (typeof bdplugins[plugin].plugin.getSettingsPanel === "function") { 58 | var panel = bdplugins[plugin].plugin.getSettingsPanel(); 59 | 60 | $(".modal-inner").off("click.bdpsm").on("click.bdpsm", function (e) { 61 | if ($("#bd-psm-id").length) { 62 | $(".bd-psm").remove(); 63 | } else { 64 | $(".bd-psm").attr("id", "bd-psm-id"); 65 | } 66 | 67 | }); 68 | $(".modal").append('
    '); 69 | $("#bd-psm-s").append(panel); 70 | } 71 | } 72 | }; 73 | 74 | PluginModule.prototype.loadPluginData = function () { 75 | var cookie = $.cookie("bd-plugins"); 76 | if (cookie != undefined) { 77 | pluginCookie = JSON.parse($.cookie("bd-plugins")); 78 | } 79 | }; 80 | 81 | PluginModule.prototype.savePluginData = function () { 82 | $.cookie("bd-plugins", JSON.stringify(pluginCookie), { 83 | expires: 365, 84 | path: '/' 85 | }); 86 | }; 87 | 88 | PluginModule.prototype.newMessage = function () { 89 | $.each(bdplugins, function () { 90 | if (!pluginCookie[this.plugin.getName()]) return; 91 | if (typeof this.plugin.onMessage === "function") { 92 | this.plugin.onMessage(); 93 | } 94 | }); 95 | }; 96 | 97 | PluginModule.prototype.channelSwitch = function () { 98 | $.each(bdplugins, function () { 99 | if (!pluginCookie[this.plugin.getName()]) return; 100 | if (typeof this.plugin.onSwitch === "function") { 101 | this.plugin.onSwitch(); 102 | } 103 | }); 104 | }; 105 | 106 | PluginModule.prototype.socketEvent = function (e, data) { 107 | $.each(bdplugins, function () { 108 | if (!pluginCookie[this.plugin.getName()]) return; 109 | if (typeof this.plugin.socketEvent === "function") { 110 | this.plugin.socketEvent(data); 111 | } 112 | }); 113 | }; 114 | 115 | PluginModule.prototype.rawObserver = function(e) { 116 | $.each(bdplugins, function() { 117 | if (!pluginCookie[this.plugin.getName()]) return; 118 | if(typeof this.plugin.observer === "function") { 119 | this.plugin.observer(e); 120 | } 121 | }); 122 | }; -------------------------------------------------------------------------------- /dev/js/10themeModule.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp ThemeModule JavaScript 2 | * Version: 1.0 3 | * Author: Jiiks | http://jiiks.net 4 | * Date: 16/12/2015 5 | * https://github.com/Jiiks/BetterDiscordApp 6 | */ 7 | 8 | var themeCookie = {}; 9 | 10 | function ThemeModule() { 11 | 12 | } 13 | 14 | ThemeModule.prototype.loadThemes = function () { 15 | this.loadThemeData(); 16 | 17 | $.each(bdthemes, function () { 18 | var name = this["name"]; 19 | var enabled = false; 20 | if (themeCookie.hasOwnProperty(name)) { 21 | if (themeCookie[name]) { 22 | enabled = true; 23 | } 24 | } else { 25 | themeCookie[name] = false; 26 | } 27 | 28 | if (enabled) { 29 | $("head").append(''); 30 | } 31 | }); 32 | }; 33 | 34 | ThemeModule.prototype.handleTheme = function (checkbox) { 35 | 36 | var cb = $(checkbox).children().find('input[type="checkbox"]'); 37 | var enabled = !cb.is(":checked"); 38 | var id = cb.attr("id").substring(2); 39 | cb.prop("checked", enabled); 40 | 41 | if (enabled) { 42 | $("head").append(''); 43 | themeCookie[id] = true; 44 | } else { 45 | $("#" + id).remove(); 46 | themeCookie[id] = false; 47 | } 48 | 49 | this.saveThemeData(); 50 | }; 51 | 52 | ThemeModule.prototype.loadThemeData = function () { 53 | var cookie = $.cookie("bd-themes"); 54 | if (cookie != undefined) { 55 | themeCookie = JSON.parse($.cookie("bd-themes")); 56 | } 57 | }; 58 | 59 | ThemeModule.prototype.saveThemeData = function () { 60 | $.cookie("bd-themes", JSON.stringify(themeCookie), { 61 | expires: 365, 62 | path: '/' 63 | }); 64 | }; -------------------------------------------------------------------------------- /dev/js/11webSocket.js: -------------------------------------------------------------------------------- 1 | /*BDSocket*/ 2 | 3 | var bdSocket; 4 | var bdws; 5 | 6 | function BdWSocket() { 7 | bdws = this; 8 | } 9 | 10 | BdWSocket.prototype.start = function () { 11 | var self = this; 12 | /* $.ajax({ 13 | method: "GET", 14 | url: "https://discordapp.com/api/gateway", 15 | headers: { 16 | authorization: localStorage.token.match(/\"(.+)\"/)[1] 17 | }, 18 | success: function (data) { 19 | self.open(data.url); 20 | } 21 | });*/ 22 | }; 23 | 24 | BdWSocket.prototype.open = function (host) { 25 | utils.log("Socket Host: " + host); 26 | try { 27 | bdSocket = new WebSocket(host); 28 | bdSocket.onopen = this.onOpen; 29 | bdSocket.onmessage = this.onMessage; 30 | bdSocket.onerror = this.onError; 31 | bdSocket.onclose = this.onClose; 32 | } catch (err) { 33 | utils.log(err); 34 | } 35 | }; 36 | 37 | BdWSocket.prototype.onOpen = function () { 38 | utils.log("Socket Open"); 39 | var data = { 40 | op: 2, 41 | d: { 42 | token: JSON.parse(localStorage.getItem('token')), 43 | properties: JSON.parse(localStorage.getItem('superProperties')), 44 | v: 3 45 | } 46 | }; 47 | bdws.send(data); 48 | }; 49 | 50 | BdWSocket.prototype.onMessage = function (e) { 51 | 52 | var packet, data, type; 53 | try { 54 | packet = JSON.parse(e.data); 55 | data = packet.d; 56 | type = packet.t; 57 | } catch (err) { 58 | utils.err(err); 59 | return; 60 | } 61 | 62 | switch (type) { 63 | case "READY": 64 | bdSocket.interval = setInterval(function(){bdws.send({ 65 | op: 1, 66 | d: Date.now() 67 | });}, data.heartbeat_interval); 68 | utils.log("Socket Ready"); 69 | break; 70 | case "PRESENCE_UPDATE": 71 | pluginModule.socketEvent("PRESENCE_UPDATE", data); 72 | break; 73 | case "TYPING_START": 74 | pluginModule.socketEvent("TYPING_START", data); 75 | break; 76 | case "MESSAGE_CREATE": 77 | pluginModule.socketEvent("MESSAGE_CREATE", data); 78 | break; 79 | case "MESSAGE_UPDATE": 80 | pluginModule.socketEvent("MESSAGE_UPDATE", data); 81 | break; 82 | default: 83 | break; 84 | } 85 | 86 | }; 87 | 88 | BdWSocket.prototype.onError = function (e) { 89 | utils.log("Socket Error - " + e.message); 90 | }; 91 | 92 | BdWSocket.prototype.onClose = function (e) { 93 | utils.log("Socket Closed - " + e.code + " : " + e.reason); 94 | clearInterval(bdSocket.interval); 95 | bdws.start(); 96 | }; 97 | 98 | BdWSocket.prototype.send = function (data) { 99 | if (bdSocket.readyState == 1) { 100 | bdSocket.send(JSON.stringify(data)); 101 | } 102 | }; 103 | 104 | BdWSocket.prototype.getSocket = function () { 105 | return bdSocket; 106 | }; -------------------------------------------------------------------------------- /dev/js/12api.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp API for Plugins 2 | * Version: 1.0 3 | * Author: Jiiks | http://jiiks.net 4 | * Date: 11/12/2015 5 | * Last Update: 11/12/2015 6 | * https://github.com/Jiiks/BetterDiscordApp 7 | * 8 | * Plugin Template: https://gist.github.com/Jiiks/71edd5af0beafcd08956 9 | */ 10 | 11 | function BdApi() {} 12 | 13 | //Joins a server 14 | //code = server invite code 15 | BdApi.joinServer = function (code) { 16 | opublicServers.joinServer(code); 17 | }; 18 | 19 | //Inject CSS to document head 20 | //id = id of element 21 | //css = custom css 22 | BdApi.injectCSS = function (id, css) { 23 | $("head").append(''); 24 | $("#" + id).html(css); 25 | }; 26 | 27 | //Clear css/remove any element 28 | //id = id of element 29 | BdApi.clearCSS = function (id) { 30 | $("#" + id).remove(); 31 | }; 32 | 33 | //Get another plugin 34 | //name = name of plugin 35 | BdApi.getPlugin = function (name) { 36 | if (bdplugins.hasOwnProperty(name)) { 37 | return bdplugins[name]["plugin"]; 38 | } 39 | return null; 40 | }; 41 | 42 | //Get ipc for reason 43 | BdApi.getIpc = function () { 44 | return betterDiscordIPC; 45 | }; 46 | 47 | //Get BetterDiscord Core 48 | BdApi.getCore = function () { 49 | return mainCore; 50 | }; 51 | 52 | //Attempts to get user id by username 53 | //Name = username 54 | //Since Discord hides users if there's too many, this will often fail 55 | BdApi.getUserIdByName = function (name) { 56 | var users = $(".member-username"); 57 | 58 | for (var i = 0; i < users.length; i++) { 59 | var user = $(users[i]); 60 | if (user.text() == name) { 61 | var avatarUrl = user.closest(".member").find(".avatar-small").css("background-image"); 62 | return avatarUrl.match(/\d+/); 63 | } 64 | } 65 | return null; 66 | }; 67 | 68 | //Attempts to get username by id 69 | //ID = user id 70 | //Since Discord hides users if there's too many, this will often fail 71 | var gg; 72 | BdApi.getUserNameById = function (id) { 73 | var users = $(".avatar-small"); 74 | 75 | for (var i = 0; i < users.length; i++) { 76 | var user = $(users[i]); 77 | var url = user.css("background-image"); 78 | if (id == url.match(/\d+/)) { 79 | return user.parent().find(".member-username").text(); 80 | } 81 | } 82 | return null; 83 | }; 84 | 85 | //Set current game 86 | //game = game 87 | BdApi.setPlaying = function (game) { 88 | bdws.send({ 89 | "op": 3, 90 | "d": { 91 | "idle_since": null, 92 | "game": { 93 | "name": game 94 | } 95 | } 96 | }); 97 | }; 98 | 99 | //Set current status 100 | //idle_since = date 101 | //status = status 102 | BdApi.setStatus = function (idle_since, status) { 103 | bdws.send({ 104 | "op": 3, 105 | "d": { 106 | "idle_since": idle_since, 107 | "game": { 108 | "name": status 109 | } 110 | } 111 | }); 112 | }; -------------------------------------------------------------------------------- /html/pstest.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | Public Servers 4 | x 5 |
    6 |
    7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
    NameCodeLanguageDescriptionJoin
    BetterDiscord4903275937ENBetterDiscord Official Server
    BetterDiscord4903275937ENBetterDiscord Official Server
    BetterDiscord4903275937ENBetterDiscord Official Server
    41 |
    42 |
    -------------------------------------------------------------------------------- /html/test.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /issues: -------------------------------------------------------------------------------- 1 | Reopening issues now that I'm actively developing this again. Feel free to reopen your issue if it's still relevant. 2 | -------------------------------------------------------------------------------- /lib/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Core": { 3 | "Version": "0.2.82" 4 | }, 5 | "EmoteModule": { 6 | "Twitch":{ 7 | "EmoteData": "emotedata_twitch.json", 8 | "EmoteUrlStart": "https://static-cdn.jtvnw.net/emoticons/v1/", 9 | "EmoteUrlEnd": "/1.0" 10 | }, 11 | "FrankerFaceZ": { 12 | "EmoteData": "emotedata_ffz.json", 13 | "EmoteUrlStart": "https://cdn.frankerfacez.com/emoticon/", 14 | "EmoteUrlEnd": "/1" 15 | }, 16 | "BetterTTV": { 17 | "EmoteData": "emotedata_bttv.json", 18 | "EmoteUrlStart": "", 19 | "EmoteUrlEnd": "" 20 | } 21 | }, 22 | "cfg": { 23 | "repo": "Jiiks", 24 | "branch": null, 25 | "beta": false, 26 | "local": false, 27 | "localServer": "http://localhost", 28 | "version": "0.2.82", 29 | "updater": null, 30 | "hash": null, 31 | "dataPath": null, 32 | "userFile": null, 33 | "os": null, 34 | "cache": { 35 | "expired": true, 36 | "days": 0 37 | }, 38 | "defaultCfg": { "cache": null }, 39 | "userCfg": { "cache": null } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /misc/uninstall.bat: -------------------------------------------------------------------------------- 1 | @ECHO off 2 | 3 | :prompt 4 | set /P c=Are you sure you want to uninstall BetterDiscord [Y/N]? 5 | echo. 6 | if /I "%c%" EQU "Y" goto :removeBetterDiscord 7 | if /I "%c%" EQU "N" goto :eof 8 | goto :prompt 9 | 10 | :removeBetterDiscord 11 | echo Removing BetterDiscord... 12 | echo. 13 | 14 | :: Delete %appdata%\BetterDiscord 15 | call:deleteFolder %appdata%\BetterDiscord 16 | 17 | :: Remove BetterDiscord from all app versions 18 | for /d %%G in ("%localappdata%\Discord\app-*") do ( 19 | call:deleteFolder "%%G\resources\node_modules\BetterDiscord" 20 | call:deleteFolder "%%G\resources\app" 21 | ) 22 | 23 | goto:end 24 | 25 | :: Checks whether a folder exists and deletes it if it does 26 | :deleteFolder 27 | if exist "%~1" ( 28 | @RD /S /Q "%~1" 29 | echo Folder "%~1" removed. 30 | ) else ( 31 | echo Folder "%~1" does not exist. 32 | ) 33 | goto:eof 34 | 35 | :end 36 | echo. 37 | echo Restarting Discord... 38 | taskkill /f /im Discord.exe 1>nul 2>nul 39 | "%localappdata%\Discord\Update.exe" --processStart Discord.exe 40 | 41 | echo. 42 | echo BetterDiscord has been removed! 43 | echo. 44 | 45 | pause 46 | -------------------------------------------------------------------------------- /misc/uninstall.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/470767179507df8fc5f359dd72f13e0c740c3068/misc/uninstall.js -------------------------------------------------------------------------------- /misc/validator.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var crypto = require('crypto'); 3 | 4 | function checksum (str, algorithm, encoding) { 5 | return crypto 6 | .createHash(algorithm || 'md5') 7 | .update(str, 'utf8') 8 | .digest(encoding || 'hex') 9 | } 10 | 11 | 12 | var dver = "0.0.283"; 13 | 14 | console.log("BetterDiscord Validator v0.1"); 15 | 16 | 17 | var discordPath = process.env.LOCALAPPDATA + "/Discord/app-" + dver + "/resources"; 18 | 19 | exists(discordPath + "/app"); 20 | exists(discordPath + "/app/app/index.js"); 21 | 22 | var bdPath = discordPath + "/node_modules/BetterDiscord"; 23 | 24 | exists(bdPath); 25 | exists(bdPath + "/package.json"); 26 | exists(bdPath + "/betterdiscord.js"); 27 | exists(bdPath + "/lib"); 28 | exists(bdPath + "/lib/BetterDiscord.js"); 29 | exists(bdPath + "/lib/config.json"); 30 | exists(bdPath + "/lib/Utils.js"); 31 | 32 | 33 | check(discordPath + "/app/app/index.js", "35CAB26E794CDA4123927F2DC932958B"); 34 | check(bdPath + "/package.json", "26EF86E0910272D3ACA1B854D2F25340"); 35 | check(bdPath + "/betterdiscord.js", "31DD3E3D37D6FD5F6C2784D06F1162C4"); 36 | check(bdPath + "/lib/BetterDiscord.js", "84D281EDF38F945A5F6DFAAA2D951A6A"); 37 | check(bdPath + "/lib/config.json", "9A6E146B64A2D2D459B081B910D60582"); 38 | check(bdPath + "/lib/Utils.js", "FD1FFCE03E999B80636D200F78383BF8"); 39 | 40 | console.log("Everything seems to be fine"); 41 | 42 | 43 | function exists(path) { 44 | 45 | console.log("Checking for " + path); 46 | var exists = fs.existsSync(path); 47 | if(exists) { 48 | console.log(path + " exists"); 49 | } else { 50 | console.log(path + " doesn't exists"); 51 | process.exit(); 52 | } 53 | } 54 | 55 | function check(path, cm) { 56 | console.log("Checking " + path + " checksum"); 57 | 58 | var read = fs.readFileSync(path); 59 | 60 | if(cm.toLowerCase() == checksum(read).toLowerCase()) { 61 | console.log(path + " checksum matches"); 62 | } else { 63 | console.log(path + " checksum mismatch"); 64 | console.log("Expected: " + cm + " Got: " + checksum(read)); 65 | process.exit(); 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "betterdiscord", 3 | "description": "Better Discord enhances Discord.", 4 | "version": "0.2.7", 5 | "homepage": "https://github.com/Jiiks/BetterDiscordApp", 6 | "license": "MIT", 7 | "main": "betterdiscord.js", 8 | "devDependencies": { 9 | "grunt-contrib-concat": "^1.0.0", 10 | "grunt-contrib-sass": "^1.0.0", 11 | "grunt-contrib-uglify": "^1.0.1" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /splice: -------------------------------------------------------------------------------- 1 | _betterDiscord = new _betterDiscord.BetterDiscord(mainWindow); 2 | _betterDiscord.init(); -------------------------------------------------------------------------------- /v2/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | plugins: ["transform-remove-strict-mode"], 3 | presets: ["es2015"], 4 | sourceMap: false 5 | } -------------------------------------------------------------------------------- /v2/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = grunt => { 2 | 'use strict'; 3 | 4 | require('load-grunt-tasks')(grunt); 5 | 6 | grunt.initConfig({ 7 | requirejs: { 8 | compileProject: { 9 | options: { 10 | include: ['src/js/core'], 11 | out: 'intermediate/requirejs.js', 12 | optimize: 'none', 13 | paths: { 14 | 'events': 'empty:', 15 | 'electron': 'empty:' 16 | } 17 | } 18 | } 19 | }, 20 | babel: { 21 | dist: { 22 | files: [{ 23 | src: ['intermediate/requirejs.js'], 24 | dest: 'intermediate/babel.js' 25 | }] 26 | } 27 | }, 28 | replace: { 29 | dist: { 30 | options: { 31 | patterns: [{ 32 | match: /\\n +/g, 33 | replacement: '' 34 | },{ 35 | match: / +/g, 36 | replacement: ' ' 37 | },{ 38 | match: /\/*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, 39 | replacement: '' 40 | }] 41 | }, 42 | files: [{ 43 | expand: true, src: ['intermediate/babel.js'], dest: '' 44 | }] 45 | }, 46 | nongreedy: { 47 | options: { 48 | patterns: [{ 49 | match: /\\n +/g, 50 | replacement: '' 51 | },{ 52 | match: / +/g, 53 | replacement: ' ' 54 | },{ 55 | match: /\/\*(.|[\r\n])*?\*\//g, 56 | replacement: '' 57 | }] 58 | }, 59 | files: [{ 60 | expand: true, src: ['intermediate/babel.js'], dest: '' 61 | }] 62 | } 63 | }, 64 | amdclean: { 65 | options: { 66 | wrap: { 67 | start: '(function() {\n\n "use strict";\n\n var electron = require("electron");\n', 68 | end: '\n\n}());' 69 | }, 70 | escodegen: { 71 | format: { 72 | indent: { 73 | style: ' ', 74 | base: 1 75 | } 76 | } 77 | }, 78 | aggressiveOptimizations: true, 79 | transformAMDChecks: false 80 | }, 81 | dist: { 82 | src: 'intermediate/babel.js', 83 | dest: 'dist/js/main.js' 84 | } 85 | 86 | }, 87 | clean: [ 88 | 'intermediate' 89 | ] 90 | }); 91 | 92 | grunt.registerTask("js", [ "requirejs", "babel", "replace", "amdclean", "clean" ]); 93 | grunt.registerTask("js-noclean", [ "requirejs", "babel", "replace", "amdclean" ]); 94 | 95 | grunt.registerTask("fastjs", ["requirejs", "babel", "replace:nongreedy", "amdclean", "clean" ]); 96 | grunt.registerTask("fastjs-noclean", ["requirejs", "babel", "replace:nongreedy", "amdclean" ]); 97 | 98 | 99 | }; -------------------------------------------------------------------------------- /v2/README.MD: -------------------------------------------------------------------------------- 1 | v2 preview for external testers -------------------------------------------------------------------------------- /v2/lib/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "core": { 3 | "version": "0.3.0" 4 | }, 5 | "Core": { 6 | "Version": "0.3.0" 7 | }, 8 | "cfg": { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /v2/lib/core.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp Core 2 | * Version: 2:1.0 3 | * Author: Jiiks | https://jiiks.net 4 | * Date: 31/10/2016 5 | * Last Update: 31/10/2016 6 | * Github: https://github.com/Jiiks/BetterDiscordApp 7 | * Git: https://github.com/Jiiks/BetterDiscordApp.git 8 | * License: MIT 9 | */ 10 | 11 | 'use strict'; 12 | 13 | const 14 | _fs = require('fs'), 15 | _config = require('./config.json'), 16 | { _utils } = require('./utils'), 17 | { _logger } = require('./utils'), 18 | { EOL } = require('os'), 19 | _os = require('os'); 20 | 21 | const _startDate = new Date(); 22 | 23 | var _cfg; 24 | 25 | // Default configs if for some reason we don't receive config params 26 | const _defaults = { 27 | installPath: (_os.platform() === 'win32' ? process.env.APPDATA : _os.platform() === 'darwin' ? `${process.env.HOME}/Library/Preferences`: `/var/local`) + '/BetterDiscord/lib', 28 | dataPath: (_os.platform() === 'win32' ? process.env.APPDATA : _os.platform() === 'darwin' ? `${process.env.HOME}/Library/Preferences`: `/var/local`) + '/BetterDiscord/data', 29 | emotesEnabled: true 30 | }; 31 | 32 | const _resources = { 33 | "mainjs": { 34 | "path": "js", 35 | "filename": "main.js", 36 | "var": "window.BetterDiscord" 37 | }, 38 | "jQuery": { 39 | "path": "vendor", 40 | "filename": "jquery-2.2.4.min.js", 41 | "var": "window.$ = window.jQuery" 42 | } 43 | }; 44 | 45 | var _self; 46 | 47 | class Core { 48 | 49 | constructor(args) { 50 | _self = this; 51 | this.continue = true; 52 | _logger.log(`v${this.__version} Loading - OS: ${_os.platform()}`); 53 | this.initConfig(args.cfg); 54 | } 55 | 56 | initConfig(args) { 57 | _cfg = _config.cfg; 58 | _cfg.installPath = args.installPath || _defaults.installPath; 59 | _cfg.dataPath = args.dataPath || _defaults.dataPath; 60 | _cfg.emotesEnabled = args.emotesEnabled || _defaults.emotesEnabled; 61 | } 62 | 63 | hook(mainWindow) { 64 | if(mainWindow === undefined) { 65 | this.exit("mainWindow is undefined!"); 66 | return; 67 | } 68 | this.mainWindow = mainWindow; 69 | this.hookEvent('dom-ready', this.domReady); 70 | } 71 | 72 | hookEvent(event, callback) { 73 | if(!this.continue) return; 74 | try { 75 | _logger.log(`Hooking ${event}`); 76 | this.mainWindow.webContents.on(event, callback); 77 | }catch(err) { 78 | this.exit(`Failed to hook event ${event}. Reason: ${err}`); 79 | } 80 | } 81 | 82 | domReady() { 83 | for(var key in _resources) { 84 | var resource = _resources[key]; 85 | _utils.requireJs(`${_cfg.installPath}/${resource.path}/${resource.filename}`, resource.var, _self.mainWindow); 86 | } 87 | 88 | _self.pluginLoader(); 89 | } 90 | 91 | pluginLoader() { 92 | 93 | } 94 | 95 | exit(reason, severity) { 96 | this.continue = false; 97 | // TODO show an actual error dialog for user 98 | _logger.log(`Quitting. Reason: ${reason}`, severity || 2); 99 | _logger.save(); 100 | } 101 | 102 | get __version() { 103 | return _config.core.version; 104 | } 105 | 106 | } 107 | 108 | exports.BetterDiscord = Core; 109 | -------------------------------------------------------------------------------- /v2/lib/main.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./core'); -------------------------------------------------------------------------------- /v2/lib/test.js: -------------------------------------------------------------------------------- 1 | var BD = require('./main'); 2 | var _bd = new BD.BetterDiscord({ cfg: { } }); -------------------------------------------------------------------------------- /v2/lib/utils.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp Utilities 2 | * Version: 2:1.0 3 | * Author: Jiiks | https://jiiks.net 4 | * Date: 31/10/2016 5 | * Last Update: 31/10/2016 6 | * Github: https://github.com/Jiiks/BetterDiscordApp 7 | * Git: https://github.com/Jiiks/BetterDiscordApp.git 8 | * License: MIT 9 | */ 10 | 11 | 'use strict'; 12 | 13 | class Utils { 14 | 15 | //Get the latest commit hash from github 16 | getHash(callback) { 17 | this.download("api.github.com", "/repos/Jiiks/BetterDiscordApp/commits/master", data => { 18 | //TODO use the new soon to be implemented tryparse 19 | callback(JSON.parse(data).sha); 20 | }); 21 | } 22 | 23 | download(host, path, callback) { 24 | _logger.log(`Downloading Resource: ${host}${path}`); 25 | var options = { 26 | host: host, 27 | path: path, 28 | headers: this.headers 29 | }; 30 | 31 | _https.get(options, res => { 32 | var data = ""; 33 | res.on('data', chunk => { 34 | data += chunk; 35 | }); 36 | res.on('end', () => { 37 | callback(data); 38 | }); 39 | }).on('error', () => { 40 | //TODO error logging 41 | callback(null); 42 | }); 43 | } 44 | 45 | requireJs(file, varstring, _window) { 46 | _logger.log(`Injecting file: ${file}`); 47 | _window.webContents.executeJavaScript(`${varstring} = require("${file}");`); 48 | } 49 | 50 | //Returns a datestring: [DD/MM/YYYY - HH:MM:SS] 51 | get dateString() { 52 | var d = new Date(); 53 | 54 | return `${("00" + (d.getDate())).slice(-2)}/` + 55 | `${("00" + d.getMonth()).slice(-2)}/` + 56 | `${d.getFullYear()} - ` + 57 | `${("00" + d.getHours()).slice(-2)}:` + 58 | `${("00" + d.getMinutes()).slice(-2)}:` + 59 | `${("00" + d.getSeconds()).slice(-2)}`; 60 | } 61 | 62 | get headers() { 63 | return { 'user-agent': 'Mozilla/5.0' }; 64 | } 65 | 66 | } 67 | 68 | class Logger { 69 | 70 | constructor() { 71 | this.logs = ""; 72 | } 73 | 74 | log(msg, severity) { 75 | var l = `[BD|${this.severity(severity)}][${_utils.dateString}] >>> ${msg}`; 76 | console.log(l); 77 | this.logs += `${l}${EOL}`; 78 | } 79 | 80 | save() { 81 | try { 82 | _fs.writeFileSync('logs.log', this.logs); 83 | }catch(err) { 84 | this.log("Failed to save logs! " + err, 2); 85 | } 86 | } 87 | 88 | severity(severity) { 89 | return { 90 | 0: "INF", 91 | 1: "WRN", 92 | 2: "ERR" 93 | }[severity||0]; 94 | } 95 | 96 | } 97 | 98 | const _utils = new Utils(), 99 | _logger = new Logger(), 100 | _fs = require('fs'), 101 | {EOL} = require('os'), 102 | _https = require('https'); 103 | 104 | exports._utils = _utils; 105 | exports._logger = _logger; -------------------------------------------------------------------------------- /v2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "betterdiscord", 3 | "description": "Discord enhancement project. v2 preview", 4 | "version": "0.3.0", 5 | "homepage": "https://github.com/Jiiks/BetterDiscordApp", 6 | "license": "MIT", 7 | "main": "lib/main.js", 8 | "devDependencies": { 9 | "grunt": "^0.4.5", 10 | "load-grunt-tasks": "^3.5.0", 11 | "grunt-requirejs": "^0.4.2", 12 | "grunt-amdclean": "^0.1.2", 13 | "grunt-babel": "^6.0.0", 14 | "babel-preset-es2015": "^6.9.0", 15 | "babel-plugin-transform-remove-strict-mode": "^0.0.2", 16 | "grunt-contrib-concat": "^1.0.1", 17 | "grunt-contrib-sass": "^1.0.0", 18 | "grunt-contrib-uglify": "^1.0.1", 19 | "grunt-contrib-cssmin": "^1.0.1", 20 | "grunt-contrib-clean": "^1.0.0", 21 | "grunt-replace": "^1.0.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /v2/src/js/api.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp Client Api 2 | * Version: 2:1.0 3 | * Author: Jiiks | https://jiiks.net 4 | * Date: 31/10/2016 5 | * Last Update: 31/10/2016 6 | * Github: https://github.com/Jiiks/BetterDiscordApp 7 | * Git: https://github.com/Jiiks/BetterDiscordApp.git 8 | * License: MIT 9 | */ 10 | 11 | 12 | define(() => { 13 | 14 | class Api { 15 | 16 | } 17 | 18 | return new Api(); 19 | 20 | }); -------------------------------------------------------------------------------- /v2/src/js/core.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp Client Core 2 | * Version: 2:1.0 3 | * Author: Jiiks | https://jiiks.net 4 | * Date: 31/10/2016 5 | * Last Update: 31/10/2016 6 | * Github: https://github.com/Jiiks/BetterDiscordApp 7 | * Git: https://github.com/Jiiks/BetterDiscordApp.git 8 | * License: MIT 9 | */ 10 | 11 | 12 | define([ 13 | "./modules/modules", 14 | "./utils", 15 | "./api", 16 | "./plugin", 17 | "./event" 18 | ], (modules, utils, api, plugin, event) => { 19 | 20 | class Core { 21 | 22 | constructor(args) { 23 | this.utils = utils; 24 | this.event = event; 25 | this.modules = modules; 26 | this.beta = true; 27 | this.alpha = true; 28 | this.plugin = plugin; 29 | } 30 | 31 | init() { 32 | utils.log(`${this.__versionString} Initializing`); 33 | } 34 | 35 | get __version() { 36 | return "2.0.0"; 37 | } 38 | 39 | get __versionString() { 40 | return `${this.__version}${this.alpha ? "A" : this.beta ? "B" : ""}`; 41 | } 42 | 43 | } 44 | 45 | window.$B = s => { return $(`[data-bd=${s}`); }; 46 | 47 | window.BD = new Core(); 48 | BD.init(); 49 | 50 | }); -------------------------------------------------------------------------------- /v2/src/js/event.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp Event emitter 2 | * Version: 2:1.0 3 | * Author: Jiiks | https://jiiks.net 4 | * Date: 31/10/2016 5 | * Last Update: 31/10/2016 6 | * Github: https://github.com/Jiiks/BetterDiscordApp 7 | * Git: https://github.com/Jiiks/BetterDiscordApp.git 8 | * License: MIT 9 | */ 10 | 11 | 12 | define(() => { 13 | 14 | const EventEmitter = new require('events').EventEmitter; 15 | 16 | class Event { 17 | 18 | constructor() { 19 | this.eventEmitter = new EventEmitter; 20 | } 21 | 22 | on(eventName, callback) { 23 | this.eventEmitter.on(eventName, callback); 24 | } 25 | 26 | emit(...args) { 27 | this.eventEmitter.emit(...args); 28 | } 29 | 30 | } 31 | 32 | return new Event(); 33 | }); -------------------------------------------------------------------------------- /v2/src/js/modules/modules.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp Client Module Defines 2 | * Version: 2:1.0 3 | * Author: Jiiks | https://jiiks.net 4 | * Date: 31/10/2016 5 | * Last Update: 31/10/2016 6 | * Github: https://github.com/Jiiks/BetterDiscordApp 7 | * Git: https://github.com/Jiiks/BetterDiscordApp.git 8 | * License: MIT 9 | */ 10 | 11 | define([ 12 | "./observermodule" 13 | ], (observerModule) => { 14 | 15 | const modules = { 16 | observerModule: observerModule 17 | }; 18 | 19 | return modules; 20 | }); -------------------------------------------------------------------------------- /v2/src/js/modules/observermodule.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp Client Observer 2 | * Version: 2:1.0 3 | * Author: Jiiks | https://jiiks.net 4 | * Date: 31/10/2016 5 | * Last Update: 31/10/2016 6 | * Github: https://github.com/Jiiks/BetterDiscordApp 7 | * Git: https://github.com/Jiiks/BetterDiscordApp.git 8 | * License: MIT 9 | */ 10 | 11 | define([], () => { 12 | 13 | class Observer { 14 | 15 | constructor() { 16 | this.mutationObserver = new MutationObserver(this.observe); 17 | this.mutationObserver.observe(document, { 18 | childList: true, 19 | subtree: true 20 | }); 21 | } 22 | 23 | observe(mutations) { 24 | 25 | mutations.forEach(mutation => { 26 | BD.event.emit("raw-mutation", mutation); 27 | }); 28 | 29 | } 30 | 31 | } 32 | 33 | return new Observer(); 34 | }); -------------------------------------------------------------------------------- /v2/src/js/plugin.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp Plugin base class 2 | * Version: 2:1.0 3 | * Author: Jiiks | https://jiiks.net 4 | * Date: 31/10/2016 5 | * Last Update: 31/10/2016 6 | * Github: https://github.com/Jiiks/BetterDiscordApp 7 | * Git: https://github.com/Jiiks/BetterDiscordApp.git 8 | * License: MIT 9 | */ 10 | 11 | 12 | define(() => { 13 | 14 | class Plugin { 15 | 16 | constructor(args) { 17 | this.info = args; 18 | } 19 | 20 | get author() { 21 | return this.info.author; 22 | } 23 | 24 | get name() { 25 | return this.info.name; 26 | } 27 | 28 | get version() { 29 | return this.info.version; 30 | 31 | } 32 | } 33 | 34 | return Plugin; 35 | 36 | }); -------------------------------------------------------------------------------- /v2/src/js/utils.js: -------------------------------------------------------------------------------- 1 | /* BetterDiscordApp Client Utilities 2 | * Version: 2:1.0 3 | * Author: Jiiks | https://jiiks.net 4 | * Date: 04/11/2016 5 | * Last Update: 31/10/2016 6 | * Github: https://github.com/Jiiks/BetterDiscordApp 7 | * Git: https://github.com/Jiiks/BetterDiscordApp.git 8 | * License: MIT 9 | */ 10 | 11 | 12 | define(() => { 13 | 14 | class Utils { 15 | 16 | constructor() { 17 | 18 | } 19 | 20 | log(msg) { 21 | console.log(`%c[BD] %c>> %c${msg}`, 'color:#3e82e5; font-weight:700', 'color:#000; font-weight:700', '') 22 | } 23 | 24 | info(msg) { 25 | console.info(`%c[BD] %c>> %c${msg}`, 'color:#3e82e5; font-weight:700', 'color:#3e82e5; font-weight:700', '') 26 | } 27 | 28 | warn(msg) { 29 | console.warn(`%c[BD] %c>> %c${msg}`, 'color:#3e82e5; font-weight:700', 'color:orange; font-weight:700', '') 30 | } 31 | 32 | err(msg) { 33 | console.error(`%c[BD] %c>> %c${msg}`, 'color:#3e82e5; font-weight:700', 'color:red; font-weight:700', '') 34 | } 35 | 36 | get dateString() { 37 | return new Date().toLocaleString("en-GB"); 38 | } 39 | 40 | get timeString() { 41 | return new Date().toTimeString().split(' ')[0]; 42 | } 43 | 44 | } 45 | 46 | return new Utils(); 47 | 48 | }); --------------------------------------------------------------------------------