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
|
#!/usr/bin/env bash
# script: wg++ (WebGrab+Plus)
# author: Nikos Toutountzoglou, nikos.toutou@protonmail.com
# rev.date: 2025-03-16
VERSION="5.3.1"
# Variables
WGPP_USR=$(whoami)
WGPP_EXE=$(basename "$0")
WGPP_USR_HOME=$(getent passwd "$WGPP_USR" | cut -d: -f6)
WGPP_CFGDIR="$WGPP_USR_HOME/wg++"
WGPP_SYS="/usr/share/wg++"
# Functions
helpMsg() {
# Display help message
cat <<EOF
WebGrab+Plus EPG/XMLTV Grabber v${VERSION}
Usage: $WGPP_EXE [options]
Options:
-d, --dir <CUSTOM_DIR> Run from custom configuration folder <CUSTOM_DIR>.
-g, --generate Create new configuration folder 'wg++' in user's home directory.
-u, --update Update to the latest 'siteini.pack' and channel list files.
-h, --help Show this help message.
Examples:
$WGPP_EXE Run using the default configuration directory ($WGPP_USR_HOME/wg++).
$WGPP_EXE -d <CUSTOM_DIR> Run using a custom configuration directory.
$WGPP_EXE -d <CUSTOM_DIR> -g Create a custom configuration folder.
$WGPP_EXE -d <CUSTOM_DIR> -u Update the custom configuration folder.
$WGPP_EXE -u Update the default configuration folder.
EOF
exit 0
}
checkReq() {
# Ensure required packages are installed
local packages=(dotnet libxml2 wget unzip sudo)
local missing=()
for p in "${packages[@]}"; do
if ! pacman -Qs "$p" >/dev/null 2>&1; then
missing+=("$p")
fi
done
if [[ ${#missing[@]} -gt 0 ]]; then
printf "[ critical ] Required package(s) not installed: %s\n" "$(IFS=", "; echo "${missing[*]}")"
printf "[ info ] Please install with: sudo pacman -S %s\n" "${missing[*]}"
exit 1
fi
}
missingSysFiles() {
# Restore missing system files if needed
if [[ ! -e "$WGPP_CFGDIR/install.sh" || ! -e "$WGPP_CFGDIR/run.net.sh" ]]; then
printf "[ info ] Restoring missing script files...\n"
if ! cp -r -u "$WGPP_SYS"/* "$WGPP_CFGDIR" 2>/dev/null; then
printf "[ critical ] Failed to restore system files to '%s'\n" "$WGPP_CFGDIR"
exit 1
fi
printf "[ info ] Restored missing script files 'install.sh' and/or 'run.net.sh'.\n"
fi
}
updateSiteIni() {
# Update siteini.pack directory or recreate it if missing
if [[ -d "$WGPP_CFGDIR/siteini.pack" ]]; then
printf "[ info ] Starting update of '%s/siteini.pack' to the latest release.\n" "$WGPP_CFGDIR"
cd "$WGPP_CFGDIR/bin.net" || {
printf "[ critical ] Cannot access '%s/bin.net' directory\n" "$WGPP_CFGDIR"
exit 1
}
if ! ./SiteIni.Pack.Update.sh; then
printf "[ critical ] SiteIni.Pack update failed\n"
exit 1
fi
printf "[ info ] SiteIni.Pack update completed successfully\n"
else
printf "[ info ] Cannot find folder 'siteini.pack'. Creating directory...\n"
if ! mkdir -p "$WGPP_CFGDIR/siteini.pack"; then
printf "[ critical ] Failed to create directory '%s/siteini.pack'\n" "$WGPP_CFGDIR"
exit 1
fi
printf "[ info ] Please re-run '%s --update' to populate 'siteini.pack'.\n" "$WGPP_EXE"
exit 1
fi
}
checkWGPPDir() {
# Check if the working directory exists
if [[ ! -d "$WGPP_CFGDIR" ]]; then
return 1
fi
return 0
}
setupCustFolder() {
if [[ -z "$cust_dir" ]]; then
printf "[ critical ] Empty custom directory input. Please specify a valid directory.\n" >&2
exit 1
fi
# Resolve the absolute path of the custom directory
WGPP_CFGDIR=$(realpath "$cust_dir" 2>/dev/null || echo "$cust_dir")
# Create the directory if it doesn't exist
if [[ ! -d "$WGPP_CFGDIR" ]]; then
printf "[ info ] Directory '%s' does not exist. Creating it now...\n" "$WGPP_CFGDIR"
if ! mkdir -p "$WGPP_CFGDIR"; then
printf "[ critical ] Failed to create directory '%s'. Please check permissions.\n" "$WGPP_CFGDIR" >&2
exit 1
fi
fi
printf "[ info ] Using configuration directory: '%s'\n" "$WGPP_CFGDIR"
}
genFolder() {
# Create a new configuration folder if it doesn't exist
if [[ ! -d "$WGPP_CFGDIR" ]]; then
printf "[ info ] Creating new configuration folder '%s'...\n" "$WGPP_CFGDIR"
if ! cp -r "$WGPP_SYS" "$WGPP_CFGDIR"; then
printf "[ critical ] Failed to copy system files to '%s'\n" "$WGPP_CFGDIR"
exit 1
fi
cd "$WGPP_CFGDIR" || {
printf "[ critical ] Cannot access '%s' directory\n" "$WGPP_CFGDIR"
exit 1
}
if ! sudo -u "$WGPP_USR" ./install.sh; then
printf "[ critical ] Installation script failed\n"
exit 1
fi
printf "[ info ] Configuration folder '%s' created successfully.\n" "$WGPP_CFGDIR"
printf "[ info ] Configure 'WebGrab++.config.xml' and run '%s' to generate EPG data.\n" "$WGPP_EXE"
exit 0
else
printf "[ info ] Configuration folder '%s' already exists.\n" "$WGPP_CFGDIR"
printf "[ info ] Use a different directory or delete the existing one first.\n"
exit 1
fi
}
runScript() {
# Execute the main script and ensure output XML is formatted
cd "$WGPP_CFGDIR" || {
printf "[ critical ] Cannot access '%s' directory\n" "$WGPP_CFGDIR"
exit 1
}
printf "[ info ] Running WebGrab++ from '%s'...\n" "$WGPP_CFGDIR"
# Create temporary file for capturing output
local tmp_output
tmp_output=$(mktemp)
# Run the script and capture output
if ! sudo -u "$WGPP_USR" ./run.net.sh 2>&1 | tee "$tmp_output"; then
printf "[ critical ] WebGrab++ execution failed\n"
rm -f "$tmp_output"
exit 1
fi
# Check for license-related errors in the output
if grep -q "Index was outside the bounds of the array" "$tmp_output" || \
grep -q "Unhandled Exception" "$tmp_output" && \
grep -q "WGLicense.log.txt" "$tmp_output"; then
printf "\n[ critical ] WebGrab++ license validation failed\n"
printf "[ info ] This error typically occurs when no valid license is found or when your license has expired.\n"
printf "[ info ] Please check the license file in '%s' and ensure it's valid.\n" "$WGPP_CFGDIR"
# If the log file exists, extract relevant license information
if [[ -f "$WGPP_CFGDIR/WGLicense.log.txt" ]]; then
printf "\n[ info ] License log information:\n"
grep -i "license\|exception\|error" "$WGPP_CFGDIR/WGLicense.log.txt" | head -10
printf "\n[ info ] For full details, see: %s/WGLicense.log.txt\n" "$WGPP_CFGDIR"
fi
printf "\n[ info ] To obtain a license, visit: https://webgrabplus.com/faq\n"
rm -f "$tmp_output"
exit 1
fi
# Clean up temporary file
rm -f "$tmp_output"
if [[ ! -e "$WGPP_CFGDIR/latest.xml" ]]; then
printf "[ critical ] Missing EPG XML data file 'latest.xml'. Check configuration and logs.\n"
exit 1
fi
printf "[ info ] Formatting XML output...\n"
if ! xmllint --format latest.xml > guide.xml 2>/dev/null; then
printf "[ warning ] xmllint formatting failed, using unformatted XML\n"
cp latest.xml guide.xml
fi
printf "[ info ] EPG data successfully saved as 'guide.xml'.\n"
exit 0
}
# Argument Parsing with Improvements
cust_dir=""
do_generate=0
do_update=0
while [[ $# -gt 0 ]]; do
case "$1" in
-d | --dir)
if [[ -n "$cust_dir" ]]; then
printf "[ critical ] The '-d|--dir' option is specified more than once\n" >&2
exit 1
fi
shift
if [[ $# -eq 0 || "$1" == -* ]]; then
printf "[ critical ] The '-d|--dir' option requires a directory path argument\n" >&2
exit 1
fi
cust_dir="$1"
setupCustFolder
;;
-g | --generate)
do_generate=1
;;
-u | --update)
do_update=1
;;
-h | --help)
helpMsg
;;
*)
printf "[ critical ] Unknown argument '%s'\n" "$1" >&2
printf "[ info ] Use '%s --help' for usage information\n" "$WGPP_EXE" >&2
exit 1
;;
esac
shift
done
# Ensure valid combinations of options
if [[ $do_generate -eq 1 && $do_update -eq 1 ]]; then
printf "[ critical ] The options '--generate' and '--update' cannot be used together\n" >&2
exit 1
fi
# Main Execution
checkReq
if [[ $do_generate -eq 1 ]]; then
genFolder
elif [[ $do_update -eq 1 ]]; then
if ! checkWGPPDir; then
printf "[ critical ] Configuration directory '%s' does not exist\n" "$WGPP_CFGDIR"
printf "[ info ] Use '%s --generate' to create it first, or specify a different directory with -d\n" "$WGPP_EXE"
exit 1
fi
updateSiteIni
else
# Default execution path (no arguments)
if ! checkWGPPDir; then
printf "[ info ] No configuration directory found at '%s'\n" "$WGPP_CFGDIR"
printf "[ info ] Use '%s --generate' to create a new configuration directory\n" "$WGPP_EXE"
helpMsg
fi
# Directory exists, proceed with normal execution
missingSysFiles
runScript
fi
# Script should not reach here, but exit cleanly if it does
exit 0
|