-
-
Notifications
You must be signed in to change notification settings - Fork 189
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from BetterDiscord/install-functions
Add install functions and prepare for distribution
- Loading branch information
Showing
28 changed files
with
747 additions
and
147 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Exists due to https://github.com/electron-userland/electron-builder/issues/4299 | ||
// Tempfix adapted from: https://gist.github.com/harshitsilly/a1bd5a405f93966aad20358ae6c4cec5 | ||
|
||
const path = require("path"); | ||
const {execSync} = require("child_process"); | ||
const fs = require("fs"); | ||
const yaml = require("js-yaml"); | ||
const {appBuilderPath} = require("app-builder-bin"); | ||
const currentWorkingDirectory = process.cwd(); | ||
const packageInfo = require(path.join(currentWorkingDirectory, "package.json")); | ||
|
||
const APP_NAME = packageInfo.build.productName; | ||
const APP_VERSION = process.argv[2] ? process.argv[2] : packageInfo.version; | ||
const APP_DIST_PATH = path.join(currentWorkingDirectory, "dist"); | ||
|
||
|
||
/* eslint-disable no-console */ | ||
module.exports = function(buildResult) { | ||
if (!buildResult.artifactPaths.some(p => p.endsWith("mac.zip"))) return console.log("No Mac build detected"); | ||
console.log("Zipping Started"); | ||
|
||
execSync( | ||
`ditto -c -k --sequesterRsrc --keepParent --zlibCompressionLevel 9 "${APP_DIST_PATH}/mac/${APP_NAME}.app" "${APP_DIST_PATH}/${APP_NAME}-${APP_VERSION}-mac.zip"` | ||
); | ||
|
||
console.log("Zipping Completed"); | ||
|
||
const APP_GENERATED_BINARY_PATH = path.join(APP_DIST_PATH, `${APP_NAME}-${APP_VERSION}-mac.zip`); | ||
try { | ||
const output = execSync( | ||
`${appBuilderPath} blockmap --input="${APP_GENERATED_BINARY_PATH}" --output="${APP_DIST_PATH}/${APP_NAME}-${APP_VERSION}-mac.zip.blockmap" --compression=gzip` | ||
); | ||
const {sha512, size} = JSON.parse(output); | ||
|
||
const ymlPath = path.join(APP_DIST_PATH, "latest-mac.yml"); | ||
const ymlData = yaml.safeLoad(fs.readFileSync(ymlPath, "utf8")); | ||
// console.log(ymlData); | ||
ymlData.sha512 = sha512; | ||
ymlData.files[0].sha512 = sha512; | ||
ymlData.files[0].size = size; | ||
const yamlStr = yaml.safeDump(ymlData); | ||
// console.log(yamlStr); | ||
fs.writeFileSync(ymlPath, yamlStr, "utf8"); | ||
console.log("Successfully updated YAML file and configurations with blockmap."); | ||
} | ||
catch (e) { | ||
console.log("Error in updating YAML file and configurations with blockmap.", e); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,138 +1,137 @@ | ||
import logs from "../stores/logs"; | ||
import {progress, status} from "../stores/installation"; | ||
import {remote, shell} from "electron"; | ||
import fs from "fs"; | ||
import {promises as fs} from "fs"; | ||
import path from "path"; | ||
import bent from "bent"; | ||
import kill from "tree-kill"; | ||
import findProcess from "find-process"; | ||
|
||
const downloadFile = bent("buffer"); | ||
|
||
function log(entry) { | ||
logs.update(a => { | ||
a.push(entry); | ||
return a; | ||
}); | ||
} | ||
|
||
let progressCache = 0; | ||
|
||
function addProgress(val) { | ||
progressCache += val; | ||
progress.set(progressCache); | ||
} | ||
|
||
function failInstallation() { | ||
const discordURL = "https://discord.gg/0Tmfo5ZbORCRqbAd"; | ||
log(""); | ||
log(`The installation seems to have failed. If this problem is recurring, join our discord community for support. ${discordURL}`); | ||
status.set("error"); | ||
} | ||
import phin from "phin"; | ||
|
||
import {log, lognewline} from "./utils/log"; | ||
import succeed from "./utils/succeed"; | ||
import fail from "./utils/fail"; | ||
import exists from "./utils/exists"; | ||
import reset from "./utils/reset"; | ||
import kill from "./utils/kill"; | ||
import {showRestartNotice} from "./utils/notices"; | ||
import doSanityCheck from "./utils/sanity"; | ||
|
||
const MAKE_DIR_PROGRESS = 30; | ||
const DOWNLOAD_PACKAGE_PROGRESS = 60; | ||
const INJECT_SHIM_PROGRESS = 90; | ||
const RESTART_DISCORD_PROGRESS = 100; | ||
|
||
const bdFolder = path.join(remote.app.getPath("appData"), "BetterDiscord"); | ||
const bdDataFolder = path.join(bdFolder, "data"); | ||
const bdPluginsFolder = path.join(bdFolder, "plugins"); | ||
const bdThemesFolder = path.join(bdFolder, "themes"); | ||
|
||
async function makeDirectories() { | ||
const folders = [bdFolder, bdDataFolder, bdThemesFolder, bdPluginsFolder]; | ||
async function makeDirectories(...folders) { | ||
const progressPerLoop = (MAKE_DIR_PROGRESS - progress.value) / folders.length; | ||
for (const folder of folders) { | ||
if (fs.existsSync(folder)) { | ||
if (await exists(folder)) { | ||
log(`✅ Directory exists: ${folder}`); | ||
progress.set(progress.value + progressPerLoop); | ||
continue; | ||
} | ||
try { | ||
fs.mkdirSync(folder); | ||
await fs.mkdir(folder); | ||
progress.set(progress.value + progressPerLoop); | ||
log(`✅ Directory created: ${folder}`); | ||
} | ||
catch { | ||
catch (err) { | ||
log(`❌ Failed to create directory: ${folder}`); | ||
failInstallation(); | ||
return; | ||
log(`❌ ${err.message}`); | ||
return err; | ||
} | ||
} | ||
progress.set(25); | ||
} | ||
|
||
const downloadUrl = `https://bd.zerebos.com/betterdiscord.asar`; | ||
const getJSON = phin.defaults({method: "GET", parse: "json", headers: {"User-Agent": "BetterDiscord Installer"}}); | ||
const downloadFile = phin.defaults({method: "GET", followRedirects: true, headers: {"User-Agent": "BetterDiscord Installer", "Accept": "application/octet-stream"}}); | ||
const asarPath = path.join(bdDataFolder, "betterdiscord.asar"); | ||
async function downloadAsar() { | ||
const buffer = await downloadFile(downloadUrl); | ||
const originalFs = require("original-fs"); // because electron doesn't like when I write asar files | ||
originalFs.writeFileSync(asarPath, buffer); | ||
} | ||
|
||
async function restartDiscord() { | ||
const results = await findProcess("name", "Discord", true); | ||
if (!results || !results.length) return; | ||
const parentPids = results.map(p => p.ppid); | ||
const discordPid = results.find(p => parentPids.includes(p.pid)); | ||
const bin = discordPid.bin; | ||
kill(discordPid.pid); | ||
shell.openExternal(bin); | ||
} | ||
|
||
|
||
export default async function(discordPaths) { | ||
progress.set(0); | ||
|
||
log("Starting installation..."); | ||
log(""); | ||
log("Locating Discord paths..."); | ||
|
||
if (!discordPaths || !discordPaths.length) { | ||
log("❌ Failed to locate required directories."); | ||
failInstallation(); | ||
return; | ||
} | ||
|
||
let downloadUrl = "https://api.github.com/repos/rauenzi/BetterDiscordApp/releases"; | ||
try { | ||
await makeDirectories(); | ||
const response = await getJSON(downloadUrl); | ||
const releases = response.body; | ||
const asset = releases[0].assets.find(a => a.name === "betterdiscord.asar"); | ||
downloadUrl = asset.url; | ||
|
||
const resp = await downloadFile(downloadUrl); | ||
const originalFs = require("original-fs").promises; // because electron doesn't like when I write asar files | ||
await originalFs.writeFile(asarPath, resp.body); | ||
} | ||
catch (err) { | ||
log(`❌ Failed to create directories - ${err.message}`); | ||
failInstallation(); | ||
return; | ||
} | ||
|
||
|
||
log(""); | ||
log(`Downloading asar file from: ${downloadUrl}`); | ||
|
||
try { | ||
await downloadAsar(); | ||
log("✅ Package downloaded"); | ||
progress.set(50); | ||
} | ||
catch (err) { | ||
log(`❌ Failed to download package - ${err.message}`); | ||
failInstallation(); | ||
return; | ||
log(`❌ Failed to download package ${downloadUrl}`); | ||
log(`❌ ${err.message}`); | ||
return err; | ||
} | ||
} | ||
|
||
log(""); | ||
log("Injecting shims..."); | ||
for (const discordPath of discordPaths) { | ||
async function injectShims(paths) { | ||
const progressPerLoop = (INJECT_SHIM_PROGRESS - progress.value) / paths.length; | ||
for (const discordPath of paths) { | ||
log("Injecting into: " + discordPath); | ||
const appPath = path.join(discordPath, "app"); | ||
const pkgFile = path.join(appPath, "package.json"); | ||
const indexFile = path.join(appPath, "index.js"); | ||
try { | ||
if (!fs.existsSync(appPath)) fs.mkdirSync(appPath); | ||
fs.writeFileSync(pkgFile, JSON.stringify({name: "betterdiscord", main: "index.js"})); | ||
fs.writeFileSync(indexFile, `require("${asarPath.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}");`); | ||
if (process.platform === "win32" || process.platform === "darwin") { | ||
if (!(await exists(appPath))) await fs.mkdir(appPath); | ||
await fs.writeFile(pkgFile, JSON.stringify({name: "betterdiscord", main: "index.js"})); | ||
await fs.writeFile(indexFile, `require("${asarPath.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}");`); | ||
} | ||
else { | ||
await fs.writeFile(path.join(discordPath, "index.js"), `require("${asarPath.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}");\nmodule.exports = require("./core.asar");`); | ||
} | ||
log("✅ Injection successful"); | ||
progress.set(progress.value + progressPerLoop); | ||
} | ||
catch (err) { | ||
log(`❌ Injection Error - ${err.message}`); | ||
failInstallation(); | ||
return; | ||
log(`❌ Could not inject shims to ${discordPath}`); | ||
log(`❌ ${err.message}`); | ||
return err; | ||
} | ||
} | ||
} | ||
|
||
|
||
export default async function(config) { | ||
await reset(); | ||
const sane = doSanityCheck(config); | ||
if (!sane) return fail(); | ||
|
||
|
||
const channels = Object.keys(config); | ||
const paths = Object.values(config); | ||
|
||
|
||
lognewline("Creating required directories..."); | ||
const makeDirErr = await makeDirectories(bdFolder, bdDataFolder, bdThemesFolder, bdPluginsFolder); | ||
if (makeDirErr) return fail(); | ||
log("✅ Directories created"); | ||
progress.set(MAKE_DIR_PROGRESS); | ||
|
||
|
||
lognewline("Downloading asar file"); | ||
const downloadErr = await downloadAsar(); | ||
if (downloadErr) return fail(); | ||
log("✅ Package downloaded"); | ||
progress.set(DOWNLOAD_PACKAGE_PROGRESS); | ||
|
||
|
||
lognewline("Injecting shims..."); | ||
const injectErr = await injectShims(paths); | ||
if (injectErr) return fail(); | ||
log("✅ Shims injected"); | ||
progress.set(INJECT_SHIM_PROGRESS); | ||
|
||
|
||
lognewline("Restarting Discord..."); | ||
const killErr = await kill(channels, (RESTART_DISCORD_PROGRESS - progress.value) / channels.length); | ||
if (killErr) showRestartNotice(); // No need to bail out and show failed | ||
else log("✅ Discord restarted"); | ||
progress.set(RESTART_DISCORD_PROGRESS); | ||
|
||
|
||
log("Installation completed!"); | ||
progress.set(100); | ||
status.set("success"); | ||
succeed(); | ||
}; |
Oops, something went wrong.