-
Notifications
You must be signed in to change notification settings - Fork 0
/
run.sh
executable file
·392 lines (344 loc) · 16.9 KB
/
run.sh
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
#!/bin/bash
{
mode=headless
#mode=nested
case $mode in
nested)
fullscreen=0
limit_fps=0
;;
headless)
fullscreen=1
limit_fps=1
;;
esac
IFS=$'\n'
CHROMIUM_CONFIG=$HOME/.config/adopt-a-developer
DIRECTORY="$(readlink -f "$(dirname "$0")")"
exit_restart() { #exit with code 2 to signify that this script wants to be restarted by the daemon
exit 2
}
error() { #red text and exit 1
echo -e "\e[91m$1\e[0m" 1>&2
exit 1
}
package_info() { #list everything dpkg knows about the $1 package. Note: the package has to be installed for this to show anything.
local package="$1"
[ -z "$package" ] && error "package_info(): no package specified!"
#list lines in /var/lib/dpkg/status between the package name and the next empty line (empty line is then removed)
sed -n -e '/^Package: '"$package"'$/,/^$/p' /var/lib/dpkg/status | head -n -1
true #this may exit with code 141 if the pipe was closed early (to be expected with grep -v)
}
package_installed_version() { #returns the installed version of the specified package-name.
local package="$1"
[ -z "$package" ] && error "package_installed_version(): no package specified!"
#find the package listed in /var/lib/dpkg/status
package_info "$package" | grep '^Version: ' | awk '{print $2}'
}
runonce() { #run command only if it's never been run before. Useful for one-time migration or setting changes.
#Runs a script in the form of stdin
script="$(< /dev/stdin)"
runonce_hash="$(sha1sum <<<"$script" | awk '{print $1}')"
if [ -s "${DIRECTORY}/runonce_hashes" ] && while read line; do [[ $line == "$runonce_hash" ]] && break; done < "${DIRECTORY}/runonce_hashes"; then
#hash found
#echo "runonce: '$script' already run before. Skipping."
true
else
#run the script.
bash <(echo "$script")
#if it succeeds, add the hash to the list to never run it again
if [ $? == 0 ];then
echo "$runonce_hash" >> "${DIRECTORY}/runonce_hashes"
else
echo "runonce(): '$script' failed. Not adding hash to list."
fi
fi
}
process_exists() { #return 0 if the $1 PID is running, otherwise 1
[ -z "$1" ] && error "process_exists(): no PID given!"
if [ -f "/proc/$1/status" ];then
return 0
else
return 1
fi
}
update_check() { #check for updates and reload the script if necessary
localhash="$(cd "$DIRECTORY" ; git rev-parse HEAD)"
latesthash="$(git ls-remote https://github.com/Botspot/adopt-a-developer HEAD | awk '{print $1}')"
if [ "$localhash" != "$latesthash" ] && [ ! -z "$latesthash" ] && [ ! -z "$localhash" ];then
echo "Auto-updating adopt-a-developer for the latest features and improvements..."
cd "$DIRECTORY"
git restore . #abandon changes to tracked files (otherwise users who modified this script are left behind)
git pull | cat #piping through cat makes git noninteractive
if [ "${PIPESTATUS[0]}" == 0 ];then
cd
echo "git pull finished. Reloading script..."
#kill labwc if running
kill $PID2KILL 2>/dev/null
#request to be restarted by the daemon
exit_restart
else
cd
echo "git pull failed. Continuing..."
fi
fi
}
less_chromium() { #hide harmless errors from chromium
grep --line-buffered -v '^close object .*: Invalid argument$\|DidStartWorkerFail chnccghejnflbccphgkncbmllhfljdfa\|Network service crashed, restarting service\|Unsupported pixel format\|Trying to Produce .* representation from a non-existent mailbox\|^libpng warning:\|Cannot create bo with format\|handshake failed; returned .*, SSL error code .*, net_error\|ReadExactly: expected .*, observed\|ERROR:wayland_event_watcher.cc\|database is locked\|Error while writing cjpalhdlnbpafiamejdnhcphjbkeiagm\.browser_action\|Failed to delete the database: Database IO error\|Message .* rejected by interface\|Failed to call method: org\.freedesktop\.ScreenSaver\.GetActive'
}
get_color_of_pixel() { #get the base64 hash of a 1x1 ppm image taken at the specified coordinates
grim -g "$1,$2 1x1" -t ppm - | base64
}
clean_chromium_config() {
#prevent "restore session" question
sed -i 's/"exited_cleanly":false/"exited_cleanly":true/g ; s/"exit_type":"Crashed"/"exit_type":"Normal"/g ; s/"crashed":true/"crashed":false/g' "$CHROMIUM_CONFIG/Default/Preferences"
#remove files left behind killed chromium
rm -rf "$CHROMIUM_CONFIG/Default/.org.chromium.Chromium."* "$CHROMIUM_CONFIG/.org.chromium.Chromium."* "$CHROMIUM_CONFIG/tmp/.org.chromium.Chromium."*
}
#don't allow this to be run with sudo
if [ $(id -u) == 0 ]; then
error "This is not designed to be run as root! Please try again as a regular user."
fi
#make sure I am being run by the daemon
if [ "$YOU_ARE_BEING_RUN_BY_DAEMON" != 1 ];then
"${DIRECTORY}/daemon.sh"
exit $?
fi
#check chromium dependency
if [ -f /usr/lib/chromium/chromium ];then
#chromium deb installed
chromium_version="$(package_installed_version chromium | sed 's/.*://g ; s/-.*//g')"
[ -z "$chromium_version" ] && error "chromium deb is installed, but failed to get a version for it!"
chromium_binary=('/usr/lib/chromium/chromium')
chromium_style=binary
elif [ -f /snap/bin/chromium ];then
#snap version of chromium is installed (most likely ubuntu)
chromium_version="$(snap info chromium | grep installed | awk '{print $2}')"
[ -z "$chromium_version" ] && error "chromium snap is installed, but failed to get a version for it!"
chromium_style=snap
else
echo "chromium needs to be installed. trying to install it now..."
sudo apt install -y chromium || error "install failed, exiting now"
echo "Chromium should now be installed. Restarting script..."
exit_restart
fi
#check dependencies
if ! command -v labwc >/dev/null ;then
echo "labwc package needs to be installed. trying to install it now..."
sudo apt install -y labwc || error "install failed, exiting now"
fi
if ! command -v wlr-randr >/dev/null ;then
echo "wlr-randr package needs to be installed. trying to install it now..."
sudo apt install -y wlr-randr || error "install failed, exiting now"
fi
if ! command -v grim >/dev/null ;then
echo "grim package needs to be installed. trying to install it now..."
sudo apt install -y grim || error "install failed, exiting now"
fi
#[ -z "$WAYLAND_DISPLAY" ] && error "For this script to work, your system needs to be using Wayland."
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/$chromium_version Chrome/$chromium_version Not/A)Brand/8 Safari/537.36"
shared_flags=(--user-agent="$user_agent" --user-data-dir="$CHROMIUM_CONFIG" --password-store=basic --disable-hang-monitor \
--disable-gpu-program-cache --disable-gpu-shader-disk-cache --disk-cache-size=$((10*1024*1024)) --media-cache-size=$((10*1024*1024)) \
--enable-features=UseOzonePlatform --ozone-platform=wayland --disable-gpu-process-crash-limit --video-threads=1 --disable-accelerated-video-decode --disable-gpu-compositing \
--num-raster-threads=1 --renderer-process-limit=1 --disable-low-res-tiling --mute-audio --no-first-run --enable-low-end-device-mode)
#GPU video decode disabled for stability reasons
#GPU compositing disabled to fix dmabuf errors on ubuntu with bad gpu drivers
#first run sequence
if [ ! -f "$CHROMIUM_CONFIG/acct-info" ];then
[ -z "$uuid" ] && read -p "Paste the UUID that Botspot gives you, then press Enter."$'\n'"Format is XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXXXXXX"$'\n'"> " uuid
if ! [[ $uuid =~ ^\{?[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{20}\}?$ ]]; then
error "Unknown UUID format for input '$uuid'. Please run this script and try again."
fi
#compile wlrctl
if [ ! -f /usr/local/bin/wlrctl ];then
echo "Compiling wlrctl tool..."
sudo apt install -y cmake libxkbcommon-dev libwayland-dev meson git || error "failed to install compile dependencies for wlrctl"
rm -rf ./wlrctl
git clone https://git.sr.ht/~brocellous/wlrctl || error "failed to download wlrctl repo"
cd wlrctl
meson setup --prefix=/usr/local build || error "failed to build wlrctl"
sudo ninja -C build install || error "failed to install wlrctl"
cd ..
rm -rf ./wlrctl
fi
echo -n "Copying config... "
rm -rf "$CHROMIUM_CONFIG"
mkdir -p "$(dirname "$CHROMIUM_CONFIG")" || error "Failed to make the config folder! You need to fix your file permissions/ownership."
cp -a "$DIRECTORY/template-acct" "$CHROMIUM_CONFIG"
#folder permissions in .config may be weird
chmod -R 755 "$CHROMIUM_CONFIG" || sudo chmod -R 755 "$CHROMIUM_CONFIG" || error "Failed to set 755 folder permissions for $CHROMIUM_CONFIG"
#make tmp directory for chromium - more reliable folder permissions than /tmp
mkdir -p "$CHROMIUM_CONFIG/tmp"
echo Done
#pick a screen resolution
resolution="$(shuf "$DIRECTORY/resolutions" | grep -v '#' | head -n1)"
[ -z "$resolution" ] && error "failed to pick a resolution"
width="$(echo "$resolution" | sed 's/x.*//g')"
height="$(echo "$resolution" | sed 's/.*x//g')"
#save UUID and screen resolution for later runs
echo -e "uuid=$uuid\nwidth=$width\nheight=$height" > "$CHROMIUM_CONFIG/acct-info" || error "Failed to create $CHROMIUM_CONFIG/acct-info file"
else #not first run
#get saved values like uuid, width, height
source "$CHROMIUM_CONFIG/acct-info"
if [ -z "$uuid" ];then
error "Failed to get uuid value from $CHROMIUM_CONFIG/acct-info - go check if that file is empty somehow."
else
echo "vid-viewer chosen UUID: $uuid"
fi
#make tmp directory for chromium - more reliable folder permissions than /tmp
if [ ! -d "$CHROMIUM_CONFIG/tmp" ];then
mkdir -p "$CHROMIUM_CONFIG/tmp"
fi
if [ ! -z "$PID2KILL" ] && process_exists "$PID2KILL" ;then
#kill other running process (may be autostarted)
echo "Another instance of this script was already running ($PID2KILL), killed it"
kill "$PID2KILL"
fi
fi
echo "vid-viewer chosen resolution: ${width}x${height}"
echo "Checking for updates..."
update_check
echo Done
export TMPDIR="$CHROMIUM_CONFIG/tmp"
#autostart, respect user's deletion from old runonce (don't create the file again if user already deleted it once)
export DIRECTORY
runonce <<"EOF"
if ! grep -q 'eaddbd9eef16066e454078ee0d6dda65f27ab5e9' "${DIRECTORY}/runonce_hashes" 2>/dev/null || [ -f ~/.config/autostart/adopt-a-developer.desktop ];then
echo "Setting up autostart..."
mkdir -p ~/.config/autostart
echo "[Desktop Entry]
Name=Adopt a Developer
Exec=${DIRECTORY}/daemon.sh
Terminal=false
Type=Application
X-GNOME-Autostart-enabled=true
Hidden=false
NoDisplay=false" > ~/.config/autostart/adopt-a-developer.desktop
echo "To disable this running on next boot, remove this file: ~/.config/autostart/adopt-a-developer.desktop"
fi
true
EOF
(read line #get data values from labwc subprocess
#echo "line was '$line'"
if [[ "$line" == WAYLAND_DISPLAY=* ]];then
eval $line #set the values of WAYLAND_DISPLAY and PID2KILL
export WAYLAND_DISPLAY #needed for x11/headless systems, where this is not already an environment variable
#run internal programs here
#add PID of sleep command keeping labwc open, to acct-info to prevent multiple instances
sed -i '/^PID2KILL/d' "$CHROMIUM_CONFIG/acct-info"
echo "PID2KILL=$PID2KILL" >> "$CHROMIUM_CONFIG/acct-info"
trap "kill $PID2KILL 2>/dev/null" EXIT #make sure labwc exits if this script is killed
#resize screen in retry loop
while ! wlr-randr | grep -qF "${width}x${height} px (current)" ;do
wlr-randr --output $(wlr-randr | head -n1 | awk '{print $1}') --custom-mode ${width}x${height} || error "screen resize failed."
sleep 1
done
while true;do
echo -e 'Message from Botspot: adopt-a-developer has encountered more backlash than I was expecting. While it has worked flawlessly from the technical side, earning roughly $2 per day from just 4 or so active devices, for now I have decided to pause it to think through what to do next.'
sleep 60m
update_check
done
echo -e "Launching hidden browser to donate to the developer...\nLeave this running as much as you can."
while true;do
#run browser with uuid to set cookies (slight chance of running again occasionally to fix issue where cookies went missing somehow)
if [ "$cookies_set" != 1 ] || (( RANDOM % 40 == 0 ));then
echo "Setting cookies... this should take less than 30 seconds"
clean_chromium_config
$chromium_binary "${shared_flags[@]}" --class=vid-viewer --start-maximized "https://mm-watch.com?u=$uuid" 2>&1 | less_chromium &
chrpid=$!
while true;do
if wlrctl toplevel find app_id:vid-viewer title:"MM Watch | Endless Entertainment - Chromium" ;then
break
elif ! process_exists "$chrpid" ;then
error "Chromium process failed to start, please review errors above"
fi
sleep 1
done
sleep 10
#check for cookie banner and dismiss it if present
if [ "$(get_color_of_pixel $((width/2+50)) $((height-70)))" == UDYKMSAxCjI1NQpEiO4= ];then
rm -rf ~/.config/adopt-a-developer ~/.config/autostart/adopt-a-developer.desktop
error "Cookie banner detected. Most likely this means you are in the EU and the developer will get no income from your device. Go let Botspot know that your UUID can be given to someone else."
echo "Dismissing cookie banner..."
#shift-tab twice, then Enter
wlrctl keyboard type $'\t' modifiers SHIFT
sleep 0.5
wlrctl keyboard type $'\t' modifiers SHIFT
sleep 0.5
wlrctl keyboard type $'\n'
sleep 5
fi
wlrctl toplevel close app_id:vid-viewer
echo "Cookies set successfully."
if [ "$cookies_set" != 1 ];then
cookies_set=1
echo cookies_set=1 >> "$CHROMIUM_CONFIG/acct-info"
fi
fi
clean_chromium_config
chromium_flags=("${shared_flags[@]}" --class=vid-viewer --start-maximized $([ $fullscreen == 1 ] && echo '--start-fullscreen') "$(shuf "$DIRECTORY/starting-links" | head -n1)")
if [ "$chromium_style" == binary ];then
$chromium_binary "${chromium_flags[@]}" 2>&1 | less_chromium &
chrpid=$!
elif [ "$chromium_style" == snap ];then
snap run --shell chromium -c "chromium_flags=() ; IFS=$'\n' ; for i in "\""${chromium_flags[*]}"\"" ;do chromium_flags+=("\"\$"i"\"") ;done ; TMPDIR=${CHROMIUM_CONFIG}/tmp WAYLAND_DISPLAY=$WAYLAND_DISPLAY DISPLAY=$DISPLAY chromium.launcher "\$"{chromium_flags[@]}" 2>&1 | less_chromium &
chrpid=$!
fi
#wait until chromium is running, then minimize it to reduce GPU usage
if [ "$limit_fps" == 1 ];then
wlrctl toplevel waitfor app_id:vid-viewer
echo "Browser window up and running as expected. All good."
sleep 5
fi
i=0
#every 10s, raise chromium window, every 50m restart chromium
while [ $i -lt 300 ];do
#inspect file allows troubleshooting without killing the browser
if [ -f "$DIRECTORY/inspect" ];then
inspect=true
else
inspect=false
fi
#raise window, then lower it immediately for 6 frames per minute
if [ "$limit_fps" == 1 ];then
wlrctl toplevel focus app_id:vid-viewer
if [ $inspect == false ];then
wlrctl toplevel minimize app_id:vid-viewer
fi
fi
#check for killed processes
if ! process_exists "$chrpid" ;then
#browser process killed, was anything else killed too?
if process_exists "$LABWC_PID" && process_exists "$PID2KILL";then
#labwc and sleep infinity subprocess still running
(error "WARNING: browser process disappeared. Waiting 60 seconds and retrying...")
sleep 60
break
elif process_exists "$PID2KILL" ;then
#labwc killed, but its sleep infinity subprocess still running: labwc crashed
kill "$PID2KILL"
(error "LABWC CRASHED!! Restarting script in 60 seconds...")
sleep 60
exit_restart
else
#labwc and sleep infinity subprocess killed, so this script must have been killed by another process
(error "browser and labwc killed, so likely another process was started. Exiting.")
exit 0
fi
fi
sleep 10
i=$((i+1))
done
#close chromium nicely, then forcefully
wlrctl toplevel close app_id:vid-viewer
sleep 5
kill "$chrpid" 2>/dev/null
update_check #check for updates again
[ "$i" == 300 ] && echo "50 minutes has elapsed, restarting browser"
done
else
error "Unknown line from labwc: $line"
fi
) < <(WLR_BACKENDS="${mode//nested/wayland}" labwc -C "$DIRECTORY/labwc" -s 'bash -c '\''echo "WAYLAND_DISPLAY=$WAYLAND_DISPLAY PID2KILL=$$ LABWC_PID=$LABWC_PID"; trap "kill $LABWC_PID 2>/dev/null" EXIT; sleep infinity'\' | \
grep --line-buffered "^WAYLAND_DISPLAY=" ; labwc_exitcode=${PIPESTATUS[0]} ; if [ "$labwc_exitcode" != 0 ];then echo "labwc exitcode was $labwc_exitcode" 1>&2 ;fi)
}