Skip to content

Instantly share code, notes, and snippets.

@noodlebox
Last active October 13, 2022 00:40
Show Gist options
  • Save noodlebox/21cdde481cb812cf212c352a4ce5289b to your computer and use it in GitHub Desktop.
Save noodlebox/21cdde481cb812cf212c352a4ce5289b to your computer and use it in GitHub Desktop.
Self-installer for BetterDiscord plugins

SelfInstaller.js

This snippet can be added to your BetterDiscord plugins to provide a simple, unintrusive self-installer.

Why do I need this?

A user downloads your plugin for BetterDiscord. Having only skimmed the #faq, he immediately double-clicks it (as he is wont to do with executable files from the internet). Then, a mysterious entity known as the Windows Script Host either spits out a non-sensical error message, or worse, provides no feedback at all. Soon afterwards, he suffers the harsh mocking of the more knowledgeable users of #support.

You can save him this embarassment.

You can save the valuable time of everyone in #support.

How does it work?

This takes advantage of JScript's conditional compilation to run an interactive self-installer (actually just a series of dialog prompts) when executed by the Windows Script Host, the default handler for .js files on Windows. Your plugin code is contained safely within the @else ... @end block, preventing the Windows Script Host from trying (and typically failing) to evaluate JavaScript syntax meant for a modern web browser. When executed under normal conditions, the self-installer's code is interpreted as a harmless comment.

Usage

Add the contents of SelfInstaller.HEADER.js after the META line of your plugin, but before any actual code. Then, to the end of your file, add the contents of SelfInstaller.FOOTER.js.

Alternatively, use the provided shell script to modify your plugin(s) in place:

$ ./patch.sh example.plugin.js

or

$ ./patch.sh *.plugin.js
#!/usr/bin/env bash
for f; do
f=$(realpath -- "$f")
cd -- "$(dirname -- "$0")"
ed -s -- "${f/#'!'/'\!'}" <<-'EOF'
$a
.
$r SelfInstaller.FOOTER.js
1a
.
2r SelfInstaller.HEADER.js
w
EOF
cd - &>/dev/null
done
/*@cc_on
@if (@_jscript)
// Offer to self-install for clueless users that try to run this directly.
var shell = WScript.CreateObject("WScript.Shell");
var fs = new ActiveXObject("Scripting.FileSystemObject");
var pathPlugins = shell.ExpandEnvironmentStrings("%APPDATA%\\BetterDiscord\\plugins");
var pathSelf = WScript.ScriptFullName;
// Put the user at ease by addressing them in the first person
shell.Popup("It looks like you mistakenly tried to run me directly. (don't do that!)", 0, "I'm a plugin for BetterDiscord", 0x30);
if (fs.GetParentFolderName(pathSelf) === fs.GetAbsolutePathName(pathPlugins)) {
shell.Popup("I'm in the correct folder already.\nJust reload Discord with Ctrl+R.", 0, "I'm already installed", 0x40);
} else if (!fs.FolderExists(pathPlugins)) {
shell.Popup("I can't find the BetterDiscord plugins folder.\nAre you sure it's even installed?", 0, "Can't install myself", 0x10);
} else if (shell.Popup("Should I copy myself to BetterDiscord's plugins folder for you?", 0, "Do you need some help?", 0x34) === 6) {
fs.CopyFile(pathSelf, fs.BuildPath(pathPlugins, fs.GetFileName(pathSelf)), true);
// Show the user where to put plugins in the future
shell.Exec("explorer " + pathPlugins);
shell.Popup("I'm installed!\nJust reload Discord with Ctrl+R.", 0, "Successfully installed", 0x40);
}
WScript.Quit();
@else @*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment