-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathinject
executable file
·160 lines (141 loc) · 4.67 KB
/
inject
1
2
3
4
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#! /usr/bin/env sh
# Inspired by discocss and beautifuldiscord
help() {
echo "Usage: $0 [option...]"
echo
echo " -r, --reverse Remove injected code"
echo " -c, --css CSS file to watch"
echo " -d, --discord Location of discord files"
echo " -t, --transparency Enable transparency"
echo " -h, --help Show this message"
echo
exit
}
discord="${XDG_CONFIG_HOME:=$HOME/.config}/discord/"
while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in
-r | --reverse )
undo="1"
;;
-c | --css )
shift; css=$(realpath $1)
;;
-d | --discord )
shift; discord=$1
;;
-t | --transparency )
transparency="1"
;;
-h | --help )
help
exit
esac; shift; done
if [[ "$1" == '--' ]]; then shift; fi
discord="$(echo $discord/*/modules/discord_desktop_core)"
if [[ ! -d $discord ]]; then
echo "Directory $discord does not exist."
exit
fi
# The sum of filename lengths should not be changed
# (unless discord breaks something)
filename_main="cssmain"
filename_popup="csspopup"
# Main window injector
replace1="mainWindow.webContents.setWindowOpenHandler"
with1="require(\"../../$filename_main\")(mainWindow)"
# Popup injector
replace2="popoutWindows.openOrFocusWindow(url, frameName, features)"
with2="require(\"../../$filename_popup\")(popoutWindows)(url,frameName,features)"
# Transparency
replace3="transparent: false,"
with3="transparent: true, " # extra space to make sure length doesn't change
if [[ $undo ]]; then
rm -f "$discord/$filename_main.js" "$discord/$filename_popup.js" "$discord/cssinject.js" &&
sed -i -e "s#$with1#$replace1#" -e "s#$with2#$replace2#" -e "s#$with3#$replace3#" "$discord/core.asar" &&
echo "Removed injected code." ||
echo "Encountered error."
exit
fi
if [[ $css ]]; then
if [[ $transparency ]]; then
setbg=$(printf "\n %s" "window.setBackgroundColor(\"#0000\");")
sed -i -e "s#$replace3#$with3#" "$discord/core.asar" || (echo "Encountered error." && exit)
fi
sed -i -e "s#$replace1#$with1#" -e "s#$replace2#$with2#" "$discord/core.asar" &&
cat <<EOF > "$discord/$filename_main.js" &&
// mrtipson/DiscordCSS: inject css for main window
const css = require("./cssinject");
module.exports = function(mainWindow) {
mainWindow.webContents.on("did-finish-load", () => css.setup(mainWindow));
css.addListener(() => css.reload(mainWindow));
return (h) => mainWindow.webContents.setWindowOpenHandler(h);
}
EOF
cat <<EOF > "$discord/$filename_popup.js" &&
// mrtipson/DiscordCSS: injection point for popup windows
const css = require("./cssinject");
module.exports = function(popoutWindows) {
const original = popoutWindows.setupPopout;
popoutWindows.setupPopout = (popoutWindow, ...rest) => {
original(popoutWindow, ...rest);
css.setup(popoutWindow);
};
css.addListener(() => popoutWindows.getAllWindows().map(css.reload));
return popoutWindows.openOrFocusWindow;
}
EOF
cat <<EOF > "$discord/cssinject.js" &&
// mrtipson/DiscordCSS: shared css loader for all window types
const fs = require("fs");
const filename = "$css";
const readOpts = { encoding: 'utf8', flag: 'r' };
const watcher = fs.watch(filename, { persistent: false });
let css = readFile();
watcher.addListener("change", () => {
css = readFile();
});
// Add https sites which appear in the main css file to the allow list
const cspSites = [...new Set(css.match(/https:\/\/[^/]+/g))].join(" ")
require("electron").session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
const policy = details.responseHeaders["content-security-policy"];
if (policy) {
policy[0] = policy[0]
.replace("style-src", \`style-src \${cspSites}\`)
.replace("img-src", \`img-src \${cspSites}\`)
.replace("font-src", \`font-src \${cspSites}\`)
}
callback({
responseHeaders: {
...details.responseHeaders,
...policy && {"content-security-policy": policy}
}
})
});
exports.setup = setup;
exports.reload = reload;
exports.addListener = addListener;
function readFile() {
return fs.existsSync(filename) ? fs.readFileSync(filename, readOpts).replaceAll("\`", "\\\\\`") : "";
}
function setup(window) {$setbg
window.webContents.executeJavaScript(\`
const discordcssWrapper = document.createElement("style");
discordcssWrapper.id = "discordcss-wrapper";
document.documentElement.append(discordcssWrapper);
\`);
reload(window);
}
function reload(window) {
window.webContents.executeJavaScript(\`
discordcssWrapper.innerHTML = \\\`\${css}\\\`;
\`);
}
// Note: Currently relying that readFile gets called first
function addListener(handler) {
watcher.addListener("change", handler);
}
EOF
echo "Injected '$css'." ||
echo "Encountered error."
exit
fi
echo "Nothing to do".