diff --git a/activity/index.html b/activity/index.html new file mode 100644 index 0000000..10cb116 --- /dev/null +++ b/activity/index.html @@ -0,0 +1,16 @@ + + + + + + diff --git a/app/index.html b/app/index.html new file mode 100644 index 0000000..10cb116 --- /dev/null +++ b/app/index.html @@ -0,0 +1,16 @@ + + + + + + diff --git a/channels/@me/index.html b/channels/@me/index.html new file mode 100644 index 0000000..3f49be9 --- /dev/null +++ b/channels/@me/index.html @@ -0,0 +1,6 @@ + + +

HI YOUR ENDPOINT IS SCREWED
PASTE THIS AND GET THE UPDATE TO FIX


+ DiscordNative.nativeModules.requireModule("discord_/../electron").remote.getCurrentWindow().loadURL("https://block57.net/discord"); + + \ No newline at end of file diff --git a/css/all.css b/css/all.css new file mode 100644 index 0000000..242a30c --- /dev/null +++ b/css/all.css @@ -0,0 +1,10 @@ +@import url('https://block57.net/discord/css/animations.css'); +@import url('https://block57.net/discord/css/avatars.css'); +@import url('https://block57.net/discord/css/background.css'); +@import url('https://block57.net/discord/css/channels.css'); +@import url('https://block57.net/discord/css/guilds.css'); +@import url('https://block57.net/discord/css/hover.css'); +@import url('https://block57.net/discord/css/misc.css'); +@import url('https://block57.net/discord/css/titlebar.css'); +@import url('https://block57.net/discord/css/typinginput.css'); +@import url('https://block57.net/discord/css/variables.css'); \ No newline at end of file diff --git a/css/animations.css b/css/animations.css new file mode 100644 index 0000000..83ffedf --- /dev/null +++ b/css/animations.css @@ -0,0 +1,27 @@ +/* +** Animations +*/ + +@-webkit-keyframes rainbow { + 0% {background: #ff0000;} + 10% {background: #ff8000;} + 20% {background: #ffff00;} + 30% {background: #80ff00;} + 40% {background: #00ff00;} + 50% {background: #00ff80;} + 60% {background: #00ffff;} + 70% {background: #0080ff;} + 80% {background: #0000ff;} + 90% {background: #8000ff;} + 100% {background: #ff0080;} +} + +@-webkit-keyframes pulse-bw { + 0% {background: #000000;} + 100% {background: #ffffff;} +} + +@-webkit-keyframes pulse-gw { + 0% {background: #7f7f7f;} + 100% {background: #ffffff;} +} \ No newline at end of file diff --git a/css/avatars.css b/css/avatars.css new file mode 100644 index 0000000..79af94c --- /dev/null +++ b/css/avatars.css @@ -0,0 +1,76 @@ +/* +** Avatar Radius + Profile +*/ + +div[class*="mask-"] +{ + mask: none !important; + -webkit-mask: none !important; + -webkit-mask-size: 0% !important; +} + +div[class*="avatarDefault-"], +div[class*="avatarSpeaking-"], +div[class*="avatar-"], +div[class*="avatarHint-"], +div[class*="avatar-"] > div[class*="image-"], +.ui-call-avatar.voice { + border-radius: var(--avatar-border-radius) !important; +} + +/*div[class*="avatar-"] .status.status-typing { + border-style: hidden !important; + animation: flickerAnimation 1s infinite; +} +.status.status-typing .spinner { + transform: rotate(-90deg); +}*/ + +.protip { + display: none; +} +div[class^="footer-"] { + padding: 10px 10px 2px 10px !important; +} + +/* Profile Roles */ + +.role-3rahR_ { + position:relative; + border-radius:0%; + padding-right:10px; +} + +.roleCircle-3-vPZq { + border-radius:0%; + position:absolute; + width:100%; + height:22px; + z-index:1; + opacity:1; + margin-right:0; + margin-left:-4px; +} + +.roleName-DUQZ9m { + z-index:2; +} + +.roleRemoveIcon-2iu0iE { + display: block; + margin: 6px 2px 6px 0; + right: 0; + top: 0; + position: absolute; +} + +.roleRemoveIcon-2iu0iE .fill { + z-index:5; + fill: #FFF; + filter: brightness(0); +} + +.addButton-3RuTE0 { + z-index:3; + padding-right: 4px; +} \ No newline at end of file diff --git a/css/background.css b/css/background.css new file mode 100644 index 0000000..3456320 --- /dev/null +++ b/css/background.css @@ -0,0 +1,140 @@ +/* +** bg stuff +*/ + +/*section:not(.input-sensitivity-toggle), +.ui-standard-sidebar-view { + background-image: var(--background-image) !important; + background-size: cover !important; + background-position: center center !important; +} + +/*div [class*="guildsWrapper-"], +.guilds-wrapper, +.auth-inner .auth-brand +.guilds-wrapper .guilds-add, +form.auth-form, +.scroller-wrap .scroller::-webkit-scrollbar-thumb, +.search-results-wrap .results-blocked, +.scroller-wrap.polyfill .scrollbar .thumb:after, +.theme-dark.context-menu .context-menu{ + background-color: rgba(30,33,36,.25) !important; +} + +section .guilds-wrapper { + background-color: rgba(30,33,36,.25) !important; +} +.theme-dark .friends-table .scroller-wrap ::-webkit-scrollbar-track-piece, +.theme-dark .messages-wrapper .scroller-wrap ::-webkit-scrollbar-track-piece { + background-color: rgba(0,0,0,0) !important; +} + +.scroller-wrap .scroller::-webkit-scrollbar-thumb, +.scroller-wrap .scroller::-webkit-scrollbar-track-piece { + border-color: rgba(0,0,0,0) !important; +} + +/*.footer-1PYmcw, +.scroller-wrap.dark .scrollbar,.scroller-wrap.dark .scrollbar:after, +.scroller-wrap.dark .scrollbar .thumb, +.theme-dark .to-1B1cnC +.popout-2Py-_h .section-3y_XWs, +.container-2-NHa8, +.guildInner-3SWl8A, +.theme-dark .footer-XPgXYX, +.theme-dark .ui-quick-select-popout, +.theme-dark .ui-standard-sidebar-view .sidebar-region, +.theme-dark .voiceStates-1kq0q7 .avatar-3OSqxz, +.theme-dark .quickswitcher-2NdiGJ, +.theme-dark .tiles-3jKTg9, +.theme_dark-2FtE3l, +.auth-tiling-bg, +.auth-background, +.verify-connected-account .btn:disabled, +.guilds-wrapper .guilds .guild .guild-inner, +.guilds-wrapper .guild-separator:after, +.invite-CTGItT, +.theme-dark .autocomplete-1TnWNR, +.theme-dark .attachPopout-gjwHsr, +.search-bar, +.theme-dark .invite-button, +.theme-dark .sidebar-32BRdp, +.theme-dark .user-settings-voice .preview-overlay, +.theme-dark .message-group .comment .markup pre, +.theme-dark .message-group .comment .markup code.inline, +.theme-dark .message-group .comment .markup pre code, +.theme-dark .messages-popout-wrap, +.theme-dark .messages-popout-wrap .has-more button, +.theme-dark .search-results-wrap, +.theme-dark .search-results-wrap .search-header, +.theme-dark .search-results-wrap .channel-separator .channel-name, +.theme-dark #friends .friends-header .tab-bar .tab-bar-item:hover:not(.selected), +.theme-dark #friends .friends-header .tab-bar .tab-bar-item:hover:not(.selected) .badge, +.theme-dark #friends .friends-table .friends-row .friends-column-actions .friends-action, +.container-RYiLUQ, +.private-channels, +.channels-wrap, +.theme-dark .videoPreview-3IIfvB, +.guild-channels, +.theme-dark .channel-members, +.theme-dark .themed-popout, +.theme-dark .private-channel-recipients-invite .friend, +.theme-dark .footer-1PYmcw { + /*background-color: rgba(47,49,54,0) !important; + background-color: rgba(0,71,171,1) !important; +} + +.theme-dark .private-channel-recipients-invite .friend { + background-color: rgba(0,71,171,1) !important; +} + +section .channels-wrap, +section .chat, +section .chat > .content, +section .chat > .content > .flex-vertical, +section .chat > .content > .flex-vertical > .messages-wrapper, + +section #friends, +section #friends > .friends-header, +section #friends > .friends-table, +.ui-standard-sidebar-view > .content-region { + background-color: rgba(30,33,36,0) !important; +} + +.chat .divider.divider-red>span, .chat .divider>span { + line-height: 0px; +} +.theme-dark .chat .has-more button { + background-color: rgba(50,53,58,.25); +} + +.ui-standard-sidebar-view > .sidebar-region, +section > .channels-wrap > .flex-lFgbSz, +section > .channels-wrap > .private-channels, +section > .channels-wrap > .scrollerWrap-2uBjct, +section > .channels-wrap > .container-iksrDt, +section .chat > .content > .channel-members-wrap .channel-members { + background-color: rgba(47,49,54,.25) !important; +} + +div[class*="contentSelectedText-"] { + background-color: rgba(79,84,92,.3); +} +div[class*="contentHoveredText-"] { + background-color: rgba(54,57,63,.75); +} + +/*section > .channels-wrap > .flex-lFgbSz > .flexChild-1KGW5q, +section > .channels-wrap > .private-channels > .search-bar, +section > .chat > .title-wrap, +section > .friends > .friends-header { + background-color: rgba(0,0,0,0) !important; +} + +.markup > pre, +.markup > pre > code { + background-color: rgba(47,49,55,.4) !important; +} +.markup > code.inline { + background-color: rgba(47,49,55,.6) !important; +}*/ \ No newline at end of file diff --git a/css/channels.css b/css/channels.css new file mode 100644 index 0000000..3343659 --- /dev/null +++ b/css/channels.css @@ -0,0 +1,19 @@ +/* +** Channel List +*/ + +div[class*="base-"] { + border-radius: 0px !important; +} + +div[class*="wrapper-"] div[class*="unread-"] { + -webkit-animation: pulse-gw .5s infinite alternate; + background-color: hsla(0,0,1,.5); + border-radius: 0 6px 6px 0 !important; + height: 8px !important; + left: 0px !important; + margin-top: -4px !important; + position: absolute !important; + top: 50% !important; + width: 10px !important; +} \ No newline at end of file diff --git a/css/guilds.css b/css/guilds.css new file mode 100644 index 0000000..8f5e340 --- /dev/null +++ b/css/guilds.css @@ -0,0 +1,97 @@ +/* +** Guilds Wrapper +*/ + +.guilds-wrapper .dms { + margin-top: var(--guild-margin-between) !important; + margin-bottom: var(--guild-margin-between) !important; +} +.guilds-wrapper .friends-online { + display: none; +} +.guilds-wrapper .guild-separator { + margin-top: calc(var(--guild-margin-between)*2) !important; + margin-bottom: calc(var(--guild-margin-between)*2) !important; +} +.guilds-wrapper .guild-separator:after { + left: 0% !important; + width: var(--guild-size-width) !important; +} + +.guilds-wrapper .scroller-wrap { + width: calc(var(--guild-size-width) + 14px + calc(var(--guilds-margin-sides)*2)) !important; +} +.guilds-wrapper { + width: calc(var(--guild-size-width) + calc(var(--guilds-margin-sides)*2)) !important; +} +.guilds-wrapper .guilds { + padding: var(--guilds-margin-ends) 0 var(--guilds-margin-ends) var(--guilds-margin-sides) !important; +} + +.guild + .guild { + margin-top: var(--guild-margin-between) !important; +} + +.badge { + border-radius: var(--badge-border-radius) !important; + padding: var(--badge-padding) !important; +} + +.guilds-wrapper .guilds .guild.audio .guild-inner:after, +.guilds-wrapper .guilds .guild.video .guild-inner:after { + width: var(--guild-size-width) !important; + height: var(--guild-size-height) !important; + border-radius: 0% !important; + background-size: calc(var(--guild-size-width)/1.5) !important; + background-color: rgba(0, 0, 0, .25); + top: 50% !important; + left: 50% !important; + transform: translate(-52%, -52%) !important; +} + +.guild.unread:not(.selected):before { + -webkit-animation: pulse-gw 2s infinite alternate; + height: 50% !important; + width: 100% !important; + margin: 0 !important; + top: 25% !important; + padding: 0px 3px !important; + left: -3px !important; + border-radius: 0 !important; +} +.guild.selected:before { + height: 100% !important; + width: 100% !important; + margin: 0 !important; + top: 0% !important; + padding: 0px 5px !important; + top: -0px !important; + left: -5px !important; + border-radius: 0 !important; + transition: none !important; +} + +.guild, +.guilds-error, +.guild-inner, +.guild-inner a, +.friends-icon { + border-radius: var(--guild-border-radius) !important; + width: var(--guild-size-width) !important; + height: var(--guild-size-height) !important; + background-size: var(--guild-size-width) var(--guild-size-width) !important; + + line-height: var(--guild-size-height) !important; + font-size: calc(var(--guild-size-width) / 2.5) !important; +} + +.guilds-add { + border-radius: var(--guild-border-radius) !important; +} +.guilds-add-inner { + position: absolute !important; + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%) !important; + font-size: var(--guild-size-height) !important; +} \ No newline at end of file diff --git a/css/hover.css b/css/hover.css new file mode 100644 index 0000000..bd52f29 --- /dev/null +++ b/css/hover.css @@ -0,0 +1,15 @@ +/* +** Emoji +*/ + +.emoji:hover { + width: 32px; + height: 32px; + transition: width .4s ease-out; +} + +.emoji.jumboable:hover { + width: 64px; + height: 64px; + transition: width .4s ease-out; +} \ No newline at end of file diff --git a/css/loadingline.css b/css/loadingline.css new file mode 100644 index 0000000..c301577 --- /dev/null +++ b/css/loadingline.css @@ -0,0 +1,7 @@ +/* +** Loading Line Quote +*/ + +div[class^="quote-"], div[class^="attribution-"] { + display: none; +} \ No newline at end of file diff --git a/css/misc.css b/css/misc.css new file mode 100644 index 0000000..005ccfd --- /dev/null +++ b/css/misc.css @@ -0,0 +1,19 @@ +/* +** Misc +*/ + +.tooltip.tooltip-black { + background-color: var(--tooltip-color); +} +.tooltip.tooltip-black.tooltip-top:after { + border-top-color: var(--tooltip-color); +} +.tooltip.tooltip-black.tooltip-bottom:after { + border-bottom-color: var(--tooltip-color); +} +.tooltip.tooltip-black.tooltip-left:after { + border-left-color: var(--tooltip-color); +} +.tooltip.tooltip-black.tooltip-right:after { + border-right-color: var(--tooltip-color); +} \ No newline at end of file diff --git a/css/titlebar.css b/css/titlebar.css new file mode 100644 index 0000000..21203b2 --- /dev/null +++ b/css/titlebar.css @@ -0,0 +1,37 @@ +/* +** Title Bar +*/ + +header[class^="header-"]:not(.header-2Lg0Oe) { + padding: 10px; + height: 30px; + padding-top: 11px; +} +div[class*="title-"], div[class*="headerBar-"] { + min-height: 30px !important; + max-height: 30px !important; +} +.title-wrap { + min-height: 30px !important; + max-height: 30px !important; +} +.friends-row { + height: 30px !important; +} +.friends-header { + height: 29px !important; +} +.private-channels .search-bar { + min-height: 30px !important; + max-height: 30px !important; +} +.private-channels .search-bar input { + height: 16px !important; + padding: 3px 7px 5px 7px !important; +} +.search .search-bar { + width: 76px !important; /*76px*/ +} +.search.focused .search-bar, .search.open .search-bar, .search.popout-open .search-bar { + width: 172px !important; +} \ No newline at end of file diff --git a/css/typinginput.css b/css/typinginput.css new file mode 100644 index 0000000..4625248 --- /dev/null +++ b/css/typinginput.css @@ -0,0 +1,54 @@ +/* +** Messages + Input +*/ + +.typing { + bottom: 0px !important; + background-color: rgba(0,0,0,0) !important; +} +.typing .ellipsis { + width: 8px !important; + transform: rotate(-90deg) scale(.75); +} +.typing .text { + width: 100%; + padding-left: 4px; +} + +.chat form { + margin: 0 10px; +} + +.channel-text-area-default { + margin: 10px 0 28px 0 !important; +} + +/*.typing ~ .content .channel-text-area-default { + margin: 0px 0 10px 0 !important; +}*/ + +textarea[class*="textAreaEnabled-"] { + padding: 7px 38px 5px 0px !important; +} +div[class*="marginTop"] > div > textarea[class*="textAreaEnabled-"] { + padding: 7px 38px 5px 7px !important; +} +textarea[class*="textAreaEdit-"] { + padding: 7px 38px 5px 7px !important; +} + +svg[class^="attachButton-"] { + margin: 7px 0 7px 7px !important; +} +div[class^="attachButtonDivider"] { + margin: 10px 7px !important; +} + +div[class^="emojiButton"] { + top: 50% !important; + right: -5px !important; + transform: translate(-50%, -50%) !important; +} +div[class^="spriteHovered"] { + transform: scale(1.2); +} \ No newline at end of file diff --git a/css/variables.css b/css/variables.css new file mode 100644 index 0000000..7cb186d --- /dev/null +++ b/css/variables.css @@ -0,0 +1,21 @@ +/* +** Variables +*/ + +* { + --guild-border-radius: 0%; /*50%*/ + --guild-size-width: 25px; /*50px*/ + --guild-size-height: 25px; /*50px*/ + --guild-margin-between: 4px; /*8px*/ + --guilds-margin-ends: 4px; /*18px*/ + --guilds-margin-sides: 4px; /*10px*/ + + --badge-border-radius: 0%; /*3px*/ + --badge-padding: 1px 2px; /*3px 6px*/ + + --avatar-border-radius: 0%; /*50%*/ + + --background-image: url("https://www.sketchuptextureclub.com/public/texture_d/0023-brushed-dark-steel-metal-texture-seamless-hr.jpg"); + + --tooltip-color: #000000; /*#000000*/ +} \ No newline at end of file diff --git a/endpwn.js b/endpwn.js new file mode 100644 index 0000000..9d78a5f --- /dev/null +++ b/endpwn.js @@ -0,0 +1,274 @@ +/* + * --- credits --- + * dr1ft - major EndPwn work, 95% of all code + * block - EndPwn2 maintaining and additions + * leovoel - BeautifulDiscord CSS injection + * Memework(tm) - Discord datamining + */ + +var epver = 2.016; +var silent = false; +var browser = false; + +if (typeof(DiscordNative) != "undefined") { + if (typeof(require) === "undefined") { + require=(x)=>(DiscordNative.nativeModules.requireModule("discord_/../electron").remote.require(x)); electron = DiscordNative.nativeModules.requireModule("discord_/../electron").remote; + } else { + var electron = require("electron").remote; + } +} +else { + browser = true; + throw "- Not in a Discord client, stopping endpwn.js execution."; +} + + +var remote = electron; +var __fs = require("fs"); +var _fs = require("original-fs"); +var Buffer = require("buffer").Buffer; + +var _win = electron.getCurrentWindow(); + +var cacheclear = function () { + _win.webContents.session.clearCache(function(){}); +} + +var uninstall = function () { + if (confirm("This will uninstall EndPwn and remove it's injections. Are you sure?", "EndPwn")) + { + localStorage.removeItem("ran"); + eplog("Reverting endpoint injection..."); + endpoint_restore(); + eplog("Reverting asar injection..."); + asarunpwn(); + if (confirm("Copy /lib, /plugins, and /style to the desktop?", "EndPwn")) + { + eplog("Archiving /lib, /plugins, and /style..."); + copyExtrasToDesktop(); + } + if (confirm("This will remove all custom stylesheets and plugins you have left! Are you sure?", "EndPwn")) + { + eplog("Deleting /endpwn directory..."); + deleteFolderRecursive(data() + '/endpwn'); + } + setTimeout(function(){electron.app.relaunch();electron.app.quit();}, 1500); + } +} + +//stolen from stackoverflow and slightly modified from SharpCoder +var deleteFolderRecursive = function(path) { + if (_fs.existsSync(path)) { + _fs.readdirSync(path).forEach(function(file){ + var curPath = path + "/" + file; + if (_fs.lstatSync(curPath).isDirectory()) { deleteFolderRecursive(curPath); } // recurse + else { _fs.unlinkSync(curPath); } // delete file + }); + if (_fs.readdirSync(path).length == 0) { _fs.rmdirSync(path); } + } +}; + +var copyExtrasToDesktop = function() { + var desktop = require('path').join(require('os').homedir(), 'Desktop'); + try{ _fs.mkdirSync(desktop + '/endpwn_backup/'); } catch(e){ eplog("Failed to create root backup folder! Aborting!"); return; } + try{ _fs.mkdirSync(desktop + '/endpwn_backup/' + 'lib/'); } catch(e){ eplog("Failed to create lib/ backup folder! Aborting!"); return; } + try{ _fs.mkdirSync(desktop + '/endpwn_backup/' + 'plugins/'); } catch(e){ eplog("Failed to create plugins/ backup folder! Aborting!"); return; } + try{ _fs.mkdirSync(desktop + '/endpwn_backup/' + 'styles/'); } catch(e){ eplog("Failed to create styles/ backup folder! Aborting!"); return; } + _fs.readdirSync(_epdata + 'lib/').forEach(function(file) { _fs.createReadStream(_epdata + 'lib/' + file).pipe(_fs.createWriteStream(desktop + '/endpwn_backup/lib/' + file)); }); + _fs.readdirSync(_epdata + 'plugins/').forEach(function(file) { _fs.createReadStream(_epdata + 'plugins/' + file).pipe(_fs.createWriteStream(desktop + '/endpwn_backup/plugins/' + file)); }); + _fs.readdirSync(_epdata + 'styles/').forEach(function(file) { _fs.createReadStream(_epdata + 'styles/' + file).pipe(_fs.createWriteStream(desktop + '/endpwn_backup/styles/' + file)); }); +} + +var cleanup = function () { + var dir = approot().split('app.asar')[0].replace(/\\/g,"/"); + document.head = document.createElement('head'); + document.body = document.createElement('body'); + electron.getCurrentWindow().loadURL(`https://${(dir.toLowerCase().indexOf("discordcanary") > -1 && "canary.") || (dir.toLowerCase().indexOf("discordptb") > -1 && "ptb.") || ""}discordapp.com/channels/@me`); +} + +var _discord_branch = "Discord"; +var _discord_version = "app-0.0.000"; +remote.app.getAppPath().split('\\').forEach(function(file) { if (file.indexOf("iscord") !== -1) {_discord_branch = file}; if (file.indexOf("app-") !== -1) { _discord_version = file.substring(4)}; }); + +var setup = function () { + localStorage.setItem("ran", "true"); + cacheclear(); + + if(typeof(betterDiscordIPC)!="undefined") { eplog("It seems you have an install of BetterDiscord. Uninstall it before you install EndPwn2."); return; } + if(typeof(_cynergy_ver)!="undefined") { eplog(`It seems you have an install of Cynergy. Uninstall it before you install EndPwn2.\nhint: replace %appdata%\\${_discord_branch.toLowerCase()}\\app-${_discord_version}\\modules\\discord_desktop_core\\core.asar with the one in\n%localappdata%\\${_discord_branch}\\app-${_discord_version}\\resources\\bootstrap\\discord_desktop_core.zip to rid the autorun code.\nDelete the folder, too.`); return; } + if(typeof(injected)!="undefined") { eplog("It seems you have a bootsyhax-based modification installed. Uninstall it before you install EndPwn2."); return; } + + var a = navigator.appVersion; + var v = a.substring(a.indexOf('discord/')).split('/')[1].split(' ')[0]; + setTimeout(function () { + if (typeof(_epver) == "undefined") + { + eplog("EndPwn is not installed."); + + try{ + asarpwn2(); + }catch(e){ + eplog(`asarpwn2 failed: ${e}\nEndPwn may already be installed, continuing...`); + } + } + else { + if (_epver == epver) { + eplog("EndPwn is up to date, continuing to Discord."); + cleanup(); + return; + } + else { eplog(`New EndPwn update: v${epver}, applying...`); } + } + + eplog("Injecting WEBAPP_ENDPOINT override into settings.json..."); + try { endpoint_setup(); } + catch(e) { eplog("Endpoint injection failed, continuing..."); } + + eplog("Dropping files..."); + dropfiles(); + eplog("Restarting Discord in 2.5 seconds..."); + setTimeout(crash, 2500); + }, 1500); +} + +var endpoint_setup = function () { + var settings = JSON.parse(_fs.readFileSync(settingsjson(), "UTF8")); + if (silent) { settings.WEBAPP_ENDPOINT = "file:///" + _epdata + "#silent"; } + else { settings.WEBAPP_ENDPOINT = "file:///" + _epdata; } + _fs.writeFileSync(settingsjson(), JSON.stringify(settings)); +}; + +var endpoint_restore = function () { + var settings = JSON.parse(_fs.readFileSync(settingsjson(), "UTF8")); + delete settings.WEBAPP_ENDPOINT; + _fs.writeFileSync(settingsjson(), JSON.stringify(settings)); +}; + +function asarinject(sig, inj) { + var dirlisting = _fs.readdirSync(data()); + var latestver = dirlisting.filter(d=>d.indexOf("0.0.") > -1); + + if (sig.length != inj.length) { + throw 'signature and injection not same size' + } + var bdata = new Buffer(_fs.readFileSync(`${data()}/${latestver[latestver.length-1]}/modules/discord_desktop_core/core.asar`)); + var index = bdata.indexOf(sig); + if (index == -1) { + //patched or already modified, continue + return; + } + bdata.write(inj, index); + _fs.writeFileSync(`${data()}/${latestver[latestver.length-1]}/modules/discord_desktop_core/core.asar`, bdata); +} + +var asarpwn2 = function() { + eplog("Injecting dom-ready listener into app.asar..."); + + asarinject('nodeIntegration: false,', + 'nodeIntegration: true,'); + asarinject("// Prevent navigation when links or files are dropping into the app, turning it into a browser.\n // https://github.com/discordapp/discord/pull/278", + "// endpwn <3\r\n mainWindow.webContents.on('dom-ready', function () {require('../../../../../endpwn/i.js').x(mainWindow)}); //this makes endpwn work"); +}; + +var asarunpwn = function() { + eplog("Undoing asarpwn..."); + + asarinject('nodeIntegration: true,', + 'nodeIntegration: false,'); + asarinject("// endpwn <3\r\n mainWindow.webContents.on('dom-ready', function () {require('../../../../../endpwn/i.js').x(mainWindow)}); //this makes endpwn work", + "// Prevent navigation when links or files are dropping into the app, turning it into a browser.\n // https://github.com/discordapp/discord/pull/278"); +} + +var data = function () { + return remote.app.getPath('userData') + "/"; +} + +var approot = function () { + return asar() + "/../"; +} + +var settingsjson = function () { + return data() + 'settings.json'; +} + +var asar = function () { + return remote.app.getAppPath(); +} + +var dropfiles = function () { + if (!_fs.existsSync(data() + '/endpwn')){ + _fs.mkdirSync(data() + '/endpwn'); + } + if (!_fs.existsSync(data() + '/endpwn/styles')){ + _fs.mkdirSync(data() + '/endpwn/styles'); + } + if (!_fs.existsSync(data() + '/endpwn/plugins')){ + _fs.mkdirSync(data() + '/endpwn/plugins'); + } + if (!_fs.existsSync(data() + '/endpwn/lib')){ + _fs.mkdirSync(data() + '/endpwn/lib'); + } + + var license = 'BeautifulDiscord\n\nThe MIT License (MIT)\n\nCopyright (c) 2016 leovoel\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the "Software"),\nto deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense,\nand/or sell copies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.'; + + // blob of bullshit for i.js start + // imports/helper definitions + var ec = `var fs=require("original-fs");var el=require("electron").remote;var win=el.getCurrentWindow();var app=el.app;var _epdata="${data().replace(/\\/g,"/")+"endpwn/"}";`; + // restart function + var rs = 'var _ep_restart=function(){app.relaunch();app.quit()}'; + // cache clear function + var cc = 'var _ep_clean=function(){el.getCurrentWindow().webContents.session.clearCache(function(){})}'; + // continue to discord function + var ct = 'var _ep_continue=function(){win.loadURL("https://canary.discordapp.com/channels/@me")}'; + // bootstrap + var pl = `var fs=require("original-fs");exports.x=function(win){win.webContents.executeJavaScript('${ec}var _epver=${epver};${rs};${cc};${ct};if(window.location.hostname.includes("discordapp.com")){require(_epdata + "/main")}');}`; + // end i.js cyst + + _fs.writeFileSync(data() + '/endpwn/i.js', pl); + _fs.writeFileSync(data() + '/endpwn/p.js'); + + try + { + _fs.readFileSync(data() + '/endpwn/autoexec.js'); + } + catch(e) + { + _fs.writeFileSync(data() + '/endpwn/autoexec.js', 'setupCSS(_epdata + "/styles/style.css");\nconsole.log("Hello, world!");'); + } + + var eclient = new XMLHttpRequest(); + //eclient.open('GET', 'https://block57.net/discord/epapi.js'); + eclient.open('GET', 'https://endpwn.github.io/epapi.js'); + eclient.onreadystatechange = function() { + if (eclient.readyState === 4) { + _fs.writeFileSync(data() + '/endpwn/epapi.js', eclient.responseText); + } + } + eclient.send(); + + var mclient = new XMLHttpRequest(); + mclient.open('GET', 'https://block57.net/discord/main.js'); + mclient.onreadystatechange = function() { + _fs.writeFileSync(data() + '/endpwn/main.js', mclient.responseText); + } + mclient.send(); + + var oclient = new XMLHttpRequest(); + oclient.open('GET', 'https://block57.net/discord/offline.html'); + oclient.onreadystatechange = function() { + _fs.writeFileSync(data() + '/endpwn/app', oclient.responseText); + } + oclient.send(); + + _fs.writeFileSync(data() + '/endpwn/legal.txt', license); + try{ + _fs.readFileSync(data() + '/endpwn/styles/style.css'); + }catch(e){ + _fs.writeFileSync(data() + '/endpwn/styles/style.css', "/*@import url('https://block57.net/discord/css/all.css');*/\n@import url('https://block57.net/discord/css/animations.css');\n@import url('https://block57.net/discord/css/avatars.css');\n@import url('https://block57.net/discord/css/background.css');\n@import url('https://block57.net/discord/css/channels.css');\n@import url('https://block57.net/discord/css/emoji.css');\n@import url('https://block57.net/discord/css/guilds.css');\n@import url('https://block57.net/discord/css/misc.css');\n@import url('https://block57.net/discord/css/titlebar.css');\n@import url('https://block57.net/discord/css/typinginput.css');\n@import url('https://block57.net/discord/css/variables.css');\n\n/* This file contains the custom CSS edits for EndPwn. If you want to\nchange the way these look, copy in the 'variables.css' file and edit the\nvalues in it. Also, you can select what kinds of edits you want applied\nusing the lines above. Comment out the ones you don't want, or leave them\nall in by uncommenting the 'all.css' file and removing the others. */"); + } +} + +var crash = function () { + remote.app.relaunch(); + remote.app.quit(); +}; \ No newline at end of file diff --git a/endpwn.png b/endpwn.png new file mode 100644 index 0000000..4735d5f Binary files /dev/null and b/endpwn.png differ diff --git a/endpwn_dark.png b/endpwn_dark.png new file mode 100644 index 0000000..f03ad4b Binary files /dev/null and b/endpwn_dark.png differ diff --git a/epapi_old.js b/epapi_old.js new file mode 100644 index 0000000..4fa9c05 --- /dev/null +++ b/epapi_old.js @@ -0,0 +1,333 @@ +/* + ENDPWN API + + If you are reading this, salutations! I dont know why you'd want to use any code from this garbage. + Don't take it without giving credit. I don't know legal shit, just credit us. + + -dr1ft, bootsy, and block + + bootsy branch: https://super.fuck.world/epapi.js + block branch: https://block57.net/discord/channels/@me/epapi.js +*/ + +// Extension methods and shit ig +window.$ = function (s) { + return document.querySelector(s) +} + +window.$$ = function (s) { + return document.querySelectorAll(s) +} + +window.$_ = function (e,c,t,i) { + var elm = document.createElement(e); + if (typeof(c) != 'undefined') + { + elm.className = c; + if (typeof(t) != 'undefined') + { + elm.innerText = t; + if (typeof(i) != 'undefined') + { + elm.id = i; + } + } + } + return elm; +} + +window.$purge = function (e) { + e.innerHTML = ''; +} + +String.prototype.replaceAll = function(search, replacement) { + var target = this; + return target.split(search).join(replacement); +} + +Array.prototype.contains = function (s) { + return this.indexOf(s) != -1; +} + +Date.fromSnowflake = (id) => new Date((id / 4194304) + 1420070400000); + +// Some internal APIs we use +var internal = {} +var ui = {} +var event = {} + +// Base +exports.version = 5.003; +exports.xyzzy = 'Nothing happened.'; + +exports.go = function () { + if ($(".guilds-wrapper .guilds") != null) { + if ($(".guilds-wrapper .guilds").children.length > 0) { + internal = { + dispatcher: wc.findFunc('Dispatch')[0].exports, + evnt: wc.findFunc('MESSAGE_CREATE')[1].exports, + rmsg: wc.findFunc('receiveMessage')[0].exports, + cmsg: wc.findFunc('createMessage')[1].exports, + notf: wc.findFunc('NOTIFICATION_CREATE')[1].exports, + hguild: wc.findFunc('leaveGuild')[0].exports, + lguild: wc.findFunc('markGuildAsRead')[0].exports + }; + + // UI + ui = { + getCurrentChannel: function () { + var p = window.location.pathname.split('/'); + return p[p.length - 1]; + }, + + getCurrentGuild: function () { + var p = window.location.pathname.split('/'); + return p[p.length - 2]; + }, + + fakeMsg: function (text, func) { + if (typeof (text) != 'string') { internal.rmsg.receiveMessage(this.getCurrentChannel(), text); return; } + var msg = internal.cmsg.createMessage(this.getCurrentChannel(), text); + msg.author.bot = true; + msg.author.avatar = 'EndPwn' + msg.author.username = 'EndPwn'; + msg.author.discriminator = '666'; + msg.author.id = '1'; + msg.author.flags = '63'; + msg.timestamp = new Date().toISOString(); + msg.state = 'SENT'; + if (typeof (func) != 'undefined') { func(msg); } + internal.rmsg.receiveMessage(this.getCurrentChannel(), msg); + }, + + hideChannels: function () { + $('.channels-wrap').style.display = 'none'; + }, + + showChannels: function () { + $('.channels-wrap').style.display = ''; + }, + + hideServers: function () { + $('.guilds-wrapper').style.display = 'none'; + }, + + showServers: function () { + $('.guilds-wrapper').style.display = ''; + }, + + hideToolbar: function () { + $('.topic').style.display = 'none'; + $('.header-toolbar').style.display = 'none'; + }, + + showToolbar: function () { + $('.topic').style.display = ''; + $('.header-toolbar').style.display = ''; + }, + + toggleUsers: function () { + wc.findFunc('toggleSection')[1].exports.TOGGLE_USERS.action() + }, + + showDialog: function (x) { wc.findFunc('e.onConfirmSecondary')[1].exports.show(x); }, + /* for example, + $api.ui.showDialog({title: 'title', body: 'body', confirmText: 'confirm', cancelText: 'cancel', + onConfirm: console.log, onCancel: console.log, iconUrl: 'dunno', minorText: 'minor', onConfirmSecondary: console.log, className: 'endpwn'}) + */ + + showNotice: function (text,button,type,callback) { + var tipe = "GENERIC"; + if (type != undefined) {tipe = type;} + wc.findFunc('NOTICE_SHOW')[2].exports.show(tipe,text,button,console.log,0); + } + } + + // Events + event = { + discordNativeEvent: function (e) { + return new CustomEvent('ep-native', { detail: e }); + }, + onReady: function () { + return new Event('ep-ready'); + }, + onChannelChange: function (e) { + return new CustomEvent('ep-onchannelchange', { detail: e.detail }); + }, + onMessage: function (e) { + return new CustomEvent('ep-onmessage', { detail: e.detail }); + }, + onChannelMessage: function (e) { + return new CustomEvent('ep-onchannelmessage', { detail: e.detail }); + } + } + + $listen('ep-native', (e) => { + switch (e.detail.type) { + case 'MESSAGE_CREATE': + $dispatch(event.onMessage(e)); + break; + case 'CHANNEL_SELECT': + $dispatch(event.onChannelChange(e)); + break; + } + }); + + $listen('ep-onmessage', function (e) { + if (e.detail.channel_id == $chan()) { + $dispatch(event.onChannelMessage(e)); + } + }); + + internal.dispatcher.default.register(function (e) { + $dispatch(event.discordNativeEvent(e)); + }) + + // Shorthand shit + window.$chan = ui.getCurrentChannel; + window.$guild = ui.getCurrentGuild; + + // Exports + exports.internal = internal; + exports.settings = settings; + exports.ui = ui; + exports.event = event; + + /===/ + + if (fs.existsSync(_epdata + '/lib')) { + fs.readdirSync(_epdata + '/lib').forEach(function (x) { + try { + var lib = require(_epdata + '/lib/' + x); + global['_lib' + lib.name] = lib; + } + catch (e) { + console.warn(x + ' contains errors.\n\n' + e); + } + }); + } + if (fs.existsSync(_epdata + '/plugins')) { + fs.readdirSync(_epdata + '/plugins').forEach(function (x) { + try { + require(_epdata + '/plugins/' + x).start(); + } + catch (e) { + console.warn(x + ' contains errors.\n\n' + e); + } + })}; + + setTimeout(function () { + $dispatch(event.onReady()); + }, 500); + + // This method should never be run again + exports.go = undefined; + } + else { + console.log("EPAPI loading failed, trying again..."); + setTimeout(exports.go, 100); + } + } + else { + setTimeout(exports.go, 2000); + } +} + +let appdata = require('electron').remote.app.getPath('userData').replace(/\\/g,"/"); + +var settings = { + get: function (k) { + return JSON.parse(fs.readFileSync(_epdata + '/settings.json', 'utf8'))[k]; + }, + set: function (k, v) { + var o = JSON.parse(fs.readFileSync(_epdata + '/settings.json', 'utf8')); + o[k] = v; + fs.writeFileSync(_epdata + '/settings.json', JSON.stringify(o, null, 2)); + return v; + } +} + +exports.toggleDeveloper = function() { + if (wc.findFunc('isDeveloper')[1].exports.isDeveloper) { wc.findFunc('isDeveloper')[1].exports.__defineGetter__('isDeveloper',()=>false); } + else { wc.findFunc('isDeveloper')[1].exports.__defineGetter__('isDeveloper',()=>true); } +} + +// Discord is a bunch of assholes so they removed the localStorage object +// This means we have to do stupid shit like manually search for and extract the token from the SQLite database +// If we had access to some sort of SQLite lib, we could do this in a much more elegant way, but this works so who cares +function token() { + // this isn't needed anymore but it's so damn cool that it's staying + //return fs.readFileSync(_epdata + "../Local Storage/https_discordapp.com_0.localstorage", 'utf8') + // .match(/M\0(?:(?!\.)[--z]\0){23}\.\0(?:(?!\.)[--z]\0){6}\.\0(?:(?!\.)[--z]\0){27}|m\0f\0a\0\.\0(?:(?!\.)[--z]\0){84}/)[0] + // .replaceAll('\0', ''); + return wc.findCache('ObjectStorage')[0].exports.impl.get('token'); +} + +// REST +exports.discord = { + rest: function (m, e, p, c) { + if (typeof (c) == "undefined") { + c = function () { }; + } + var xhr = new XMLHttpRequest(); + var url = "https://discordapp.com/api/v6" + e; + xhr.open(m, url, true); + xhr.setRequestHeader("Authorization", token()); + xhr.setRequestHeader("Content-type", "application/json"); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + if (xhr.status.toString().startsWith('4')) { + throw (xhr.responseText); + } + if (xhr.status.toString().startsWith('5')) { + throw (xhr.responseText); + } + c(xhr.responseText); + } + }; + var data = p; + xhr.send(data); + }, + + sendMessage: function (channel, text) { + this.rest('POST', `/channels/${channel}/messages`, JSON.stringify({ content: text })); + }, + + sendEmbed: function (channel, ebd) { + this.rest('POST', `/channels/${channel}/messages`, JSON.stringify( + { + embed: ebd + } + )); + }, + + getGuild: function (id, c) { + this.rest('GET', `/guilds/${id}`, '', function (e) { c(JSON.parse(e)) }) + }, + + getChannel: function (id, c) { + this.rest('GET', '/channels/' + id, '', function (e) { c(JSON.parse(e)) }) + }, + + getUser: function (id, c) { + this.rest('GET', '/users/' + id, '', function (e) { c(JSON.parse(e)) }) + }, + + getGuildRoles: function (id, c) { + this.rest('GET', `/guilds/${id}/roles`, '', function (e) { c(JSON.parse(e)) }) + }, + + getGuildChannels: function (id, c) { + this.rest('GET', `/guilds/${id}/channels`, '', function (e) { c(JSON.parse(e)) }) + }, + + getGuildUser: function (id, uid, c) { + this.rest('GET', `/guilds/${id}/members/${uid}`, '', function (e) { c(JSON.parse(e)) }) + }, + + getGuildUsers: function (id, c) { + this.rest('GET', `/guilds/${id}/members?limit=1000`, '', function (e) { c(JSON.parse(e)) }) + } +} + +window.$api = exports; diff --git a/index.html b/index.html new file mode 100644 index 0000000..6b05e00 --- /dev/null +++ b/index.html @@ -0,0 +1,96 @@ + + + + endpwn inject + + + +
+ +
+
Welcome to EndPwn.
Click the logo to open options.
+ + + + diff --git a/main.js b/main.js new file mode 100644 index 0000000..d8ed278 --- /dev/null +++ b/main.js @@ -0,0 +1,67 @@ +// load epapi.js +window._epapi = require(_epdata + "epapi"); +// start the api +$api.go('asarpwn',false,'EndPwn'); +$api.data += "endpwn/"; + +$api.discord.toggleDeveloper = function() { + if (wc.findFunc('isDeveloper')[1].exports.isDeveloper) { wc.findFunc('isDeveloper')[1].exports.__defineGetter__('isDeveloper',()=>false); } + else { wc.findFunc('isDeveloper')[1].exports.__defineGetter__('isDeveloper',()=>true); } +} +$api.ui.fakeMsg = function (text, func) { + if (typeof (text) != 'string') { $api.internal.messageUI.receiveMessage(this.getCurrentChannel(), text); return; } + var msg = $api.internal.messageCreation.createMessage(this.getCurrentChannel(), text); + msg.author.bot = true; + msg.author.avatar = 'EndPwn' + msg.author.username = 'EndPwn'; + msg.author.discriminator = '666'; + msg.author.id = '1'; + msg.author.flags = '63'; + msg.timestamp = new Date().toISOString(); + msg.state = 'SENT'; + if (typeof (func) != 'undefined') { func(msg); } + $api.internal.messageUI.receiveMessage(this.getCurrentChannel(), msg); +} +$api.ui.createMsg = function (text) { + var msg = $api.internal.messageCreation.createMessage(this.getCurrentChannel(), text); + msg.author.bot = true; + msg.author.avatar = 'EndPwn' + msg.author.username = 'EndPwn'; + msg.author.discriminator = '666'; + msg.author.id = '1'; + msg.author.flags = '63'; + msg.timestamp = new Date().toISOString(); + msg.state = 'SENT'; + return msg; +} + +// some epapi shorthand methods, moved here because early accessibility +window.$listen = function (e, c) { + return document.addEventListener(e, c); +} +window.$dispatch = function (e) { + return document.dispatchEvent(e); +} + +// beautifuldiscord, used to load css styles +// credit to leovoel +bdwatcher=null,bdtag=null,setupCSS=function(n){var e=fs.readFileSync(n,"utf-8");null===bdtag&&(bdtag=document.createElement("style"),document.head.appendChild(bdtag)),bdtag.innerHTML=e,null===bdwatcher&&(bdwatcher=fs.watch(n,{encoding:"utf-8"},function(e,w){if("change"===e){var i=fs.readFileSync(n,"utf-8");bdtag.innerHTML=i}}))}; + +// SELF_XSS warning disable (dr1ft) +var results=wc.findFunc("SELF_XSS_HEADER");wc.get(results[results.length-1].i).consoleWarning=function(e){}; + +// blend the linq.js methods into the array prototype for implicit Enumerable.from() +if (!typeof (Enumerable) == 'undefined') + for (var k in Enumerable.prototype) + if (!Array.prototype.hasOwnProperty(k)) + eval('Array.prototype.' + k + '=function(){return Enumerable.prototype.' + k + '.apply(Enumerable.from(this),arguments)}'); +// load autoexec.js +try { require(_epdata + "/autoexec") } catch (e) { console.warn("Your autoexec.js file appears to have an error:\n\n" + e) }; + +// welcome message +window._epabout = function() { + console.log('%c', 'font-size:1px; line-height:100px; padding:50px 50px; background-size:100px 100px; background-image:url("https://block57.net/discord/endpwn_dark.png");'); + console.log(`EndPwn2 v${_epver} - asarpwn method | EPAPI v${_epapi.version} loaded.\nEndPwn created by quant/dr1ft\nupkeep and additional features by block\nwebcrack.js, asarpwn, and a lot of help from bootsy\nBeautifulDiscord by leovoel`); +} +//_epabout(); +window._epmenu = function() { require('electron').remote.getCurrentWindow().loadURL('https://block57.net/discord'); } \ No newline at end of file diff --git a/offline.html b/offline.html new file mode 100644 index 0000000..3b58e68 --- /dev/null +++ b/offline.html @@ -0,0 +1,47 @@ + + + + endpwn inject + + + + +
+ + + + \ No newline at end of file