-
Notifications
You must be signed in to change notification settings - Fork 244
/
ebook2audiobook.sh
executable file
·300 lines (279 loc) · 9.05 KB
/
ebook2audiobook.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
#!/usr/bin/env bash
PYTHON_VERSION="3.12"
export TTS_CACHE="./models"
ARGS="$@"
# Declare an associative array
declare -A arguments
# Parse arguments
while [[ "$#" -gt 0 ]]; do
case "$1" in
--*)
key="${1/--/}" # Remove leading '--'
if [[ -n "$2" && ! "$2" =~ ^-- ]]; then
# If the next argument is a value (not another option)
arguments[$key]="$2"
shift # Move past the value
else
# Set to true for flags without values
arguments[$key]=true
fi
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
shift # Move to the next argument
done
NATIVE="native"
DOCKER_UTILS="docker_utils"
FULL_DOCKER="full_docker"
SCRIPT_MODE="$NATIVE"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WGET=$(which wget 2>/dev/null)
REQUIRED_PROGRAMS=("calibre" "ffmpeg")
DOCKER_UTILS_IMG="utils"
PYTHON_ENV="python_env"
CURRENT_ENV=""
if [[ "$OSTYPE" = "darwin"* ]]; then
CONDA_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh"
else
CONDA_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh"
fi
CONDA_INSTALLER=/tmp/Miniconda3-latest.sh
CONDA_INSTALL_DIR=$HOME/miniconda3
CONDA_PATH=$HOME/miniconda3/bin
CONDA_ENV=~/miniconda3/etc/profile.d/conda.sh
CONFIG_FILE="$HOME/.bashrc"
PATH="$CONDA_PATH:$PATH"
declare -a programs_missing
# Check if the current script is run inside a docker container
if [[ -n "$container" || -f /.dockerenv ]]; then
SCRIPT_MODE="$FULL_DOCKER"
else
if [[ -n "${arguments['script_mode']+exists}" ]]; then
if [ "${arguments['script_mode']}" = "$NATIVE" ] || [ "${arguments['script_mode']}" = "$DOCKER_UTILS" ]; then
SCRIPT_MODE="${arguments['script_mode']}"
fi
fi
fi
# Check if running in a Conda or Python virtual environment
if [[ -n "$CONDA_DEFAULT_ENV" ]]; then
CURRENT_ENV="$CONDA_PREFIX"
elif [[ -n "$VIRTUAL_ENV" ]]; then
CURRENT_ENV="$VIRTUAL_ENV"
fi
# If neither environment variable is set, check Python path
if [[ -z "$CURRENT_ENV" ]]; then
PYTHON_PATH=$(which python 2>/dev/null)
if [[ ( -n "$CONDA_PREFIX" && "$PYTHON_PATH" == "$CONDA_PREFIX/bin/python" ) || ( -n "$VIRTUAL_ENV" && "$PYTHON_PATH" == "$VIRTUAL_ENV/bin/python" ) ]]; then
CURRENT_ENV="${CONDA_PREFIX:-$VIRTUAL_ENV}"
fi
fi
# Output result if a virtual environment is detected
if [[ -n "$CURRENT_ENV" ]]; then
echo -e "Current python virtual environment detected: $CURRENT_ENV."
echo -e "This script runs with its own virtual env and must be out of any other virtual environment when it's launched."
echo -e "If you are using miniconda then you would type in:"
echo -e "conda deactivate"
exit 1
fi
function required_programs_check {
local programs=("$@")
for program in "${programs[@]}"; do
if ! command -v "$program" >/dev/null 2>&1; then
echo -e "\e[33m$program is not installed.\e[0m"
programs_missing+=($program)
fi
done
local count=${#programs_missing[@]}
if [[ $count -eq 0 ]]; then
return 0
else
return 1
fi
}
function install_programs {
echo -e "\e[33mInstalling required programs. NOTE: you must have 'sudo' priviliges or it will fail.\e[0m"
if [[ "$OSTYPE" = "darwin"* ]]; then
PACK_MGR="brew install"
if ! command -v brew &> /dev/null; then
echo -e "\e[33mHomebrew is not installed. Installing Homebrew...\e[0m"
/usr/bin/env bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
else
if command -v emerge &> /dev/null; then
PACK_MGR="sudo emerge"
elif command -v dnf &> /dev/null; then
PACK_MGR="sudo dnf install"
PACK_MGR_OPTIONS="-y"
elif command -v yum &> /dev/null; then
PACK_MGR="sudo yum install"
PACK_MGR_OPTIONS="-y"
elif command -v zypper &> /dev/null; then
PACK_MGR="sudo zypper install"
PACK_MGR_OPTIONS="-y"
elif command -v pacman &> /dev/null; then
PACK_MGR="sudo pacman -Sy"
elif command -v apt-get &> /dev/null; then
sudo apt-get update
PACK_MGR="sudo apt-get install"
PACK_MGR_OPTIONS="-y"
elif command -v apk &> /dev/null; then
PACK_MGR="sudo apk add"
else
echo "Cannot recognize your applications package manager. Please install the required applications manually."
return 1
fi
fi
if [ -z "$WGET" ]; then
echo -e "\e[33m wget is missing! trying to install it... \e[0m"
result=$(eval "$PACK_MGR wget $PACK_MGR_OPTIONS" 2>&1)
result_code=$?
if [ $result_code -eq 0 ]; then
WGET=$(which wget 2>/dev/null)
else
echo "Cannot 'wget'. Please install 'wget' manually."
return 1
fi
fi
for program in "${programs_missing[@]}"; do
if [ "$program" = "calibre" ];then
# avoid conflict with calibre builtin lxml
pip uninstall lxml -y 2>/dev/null
echo -e "\e[33mInstalling Calibre...\e[0m"
if [[ "$OSTYPE" = "darwin"* ]]; then
eval "$PACK_MGR --cask calibre"
else
$WGET -nv -O- https://download.calibre-ebook.com/linux-installer.sh | sh /dev/stdin
fi
if command -v calibre >/dev/null 2>&1; then
echo -e "\e[32m===============>>> Calibre is installed! <<===============\e[0m"
else
echo "Calibre installation failed."
fi
else
eval "$PACK_MGR $program $PKG_MGR_OPTIONS"
if command -v $program >/dev/null 2>&1; then
echo -e "\e[32m===============>>> $program is installed! <<===============\e[0m"
else
echo "$program installation failed."
fi
fi
done
if required_programs_check "${REQUIRED_PROGRAMS[@]}"; then
return 0
else
echo -e "\e[33mYou can run 'ebook2audiobook.sh --script_mode docker_utils' to avoid to install $REQUIRED_PROGRAMS natively.\e[0m"
return 1
fi
}
function conda_check {
if ! command -v conda &> /dev/null; then
echo -e "\e[33mconda is not installed!\e[0m"
echo -e "\e[33mDownloading conda installer...\e[0m"
wget -O "$CONDA_INSTALLER" "$CONDA_URL"
if [[ -f "$CONDA_INSTALLER" ]]; then
echo -e "\e[33mInstalling Miniconda...\e[0m"
bash "$CONDA_INSTALLER" -u -b -p "$CONDA_INSTALL_DIR"
rm -f "$CONDA_INSTALLER"
if [[ -f "$CONDA_INSTALL_DIR/bin/conda" ]]; then
conda init
echo -e "\e[32m===============>>> conda is installed! <<===============\e[0m"
else
echo -e "\e[31mconda installation failed.\e[0m"
return 1
fi
else
echo -e "\e[31mFailed to download Miniconda installer.\e[0m"
echo -e "\e[33mI'ts better to use the install.sh to install everything needed.\e[0m"
return 1
fi
fi
if [[ ! -d $SCRIPT_DIR/$PYTHON_ENV ]]; then
# Use this condition to chmod writable folders once
chmod -R 777 ./audiobooks ./tmp ./models
conda create --prefix $SCRIPT_DIR/$PYTHON_ENV python=$PYTHON_VERSION -y
source $CONDA_ENV
conda activate $SCRIPT_DIR/$PYTHON_ENV
python -m pip install --upgrade pip
python -m pip install --upgrade -r requirements.txt --progress-bar=on
conda deactivate
fi
return 0
}
function docker_check {
if ! command -v docker &> /dev/null; then
echo -e "\e[33m docker is missing! trying to install it... \e[0m"
if [[ "$OSTYPE" == "darwin"* ]]; then
echo "Installing Docker using Homebrew..."
$PACK_MGR --cask docker $PACK_MGR_OPTIONS
else
$WGET -qO get-docker.sh https://get.docker.com && \
sudo sh get-docker.sh
sudo systemctl start docker
sudo systemctl enable docker
docker run hello-world
rm -f get-docker.sh
fi
echo -e "\e[32m===============>>> docker is installed! <<===============\e[0m"
docker_build
else
# Check if Docker service is running
if docker info >/dev/null 2>&1; then
if [[ "$(docker images -q $DOCKER_UTILS_IMG 2> /dev/null)" = "" ]]; then
docker_build
fi
else
echo -e "\e[33mDocker is not running\e[0m"
return 1
fi
fi
return 0
}
function docker_build {
# Check if the Docker socket is accessible
if [[ -e /var/run/docker.sock || -e /run/docker.sock ]]; then
echo -e "\e[33mDocker image '$DOCKER_UTILS_IMG' not found. Trying to build it...\e[0m"
docker build -f DockerfileUtils -t utils .
else
echo -e "\e[33mcannot connect to docker socket. Check if the docker socket is running.\e[0m"
fi
}
if [ "$SCRIPT_MODE" = "$FULL_DOCKER" ]; then
echo -e "\e[33mRunning in $FULL_DOCKER mode\e[0m"
python app.py --script_mode $SCRIPT_MODE $ARGS
elif [[ "$SCRIPT_MODE" == "$NATIVE" || "$SCRIPT_MODE" = "$DOCKER_UTILS" ]]; then
pass=true
if [ "$SCRIPT_MODE" == "$NATIVE" ]; then
echo -e "\e[33mRunning in $NATIVE mode\e[0m"
if ! required_programs_check "${REQUIRED_PROGRAMS[@]}"; then
if ! install_programs; then
pass=false
fi
fi
else
echo -e "\e[33mRunning in $DOCKER_UTILS mode\e[0m"
if conda_check; then
if docker_check; then
source $CONDA_ENV
conda activate $SCRIPT_DIR/$PYTHON_ENV
python app.py --script_mode $DOCKER_UTILS $ARGS
conda deactivate
fi
fi
fi
if [ $pass = true ]; then
if conda_check; then
source $CONDA_ENV
conda activate $SCRIPT_DIR/$PYTHON_ENV
python app.py --script_mode $SCRIPT_MODE $ARGS
conda deactivate
fi
fi
else
echo -e "\e[33mebook2audiobook is not correctly installed or run.\e[0m"
fi
exit 0