-
Notifications
You must be signed in to change notification settings - Fork 4
/
insta_update.sh
executable file
·314 lines (287 loc) · 12.3 KB
/
insta_update.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
#!/bin/sh
########################################################################
# insta_update.sh: Instagram Content Update Script for Subdirectories
#
# Description:
# This script navigates to a specified directory and executes an Instagram
# content downloader script in each subdirectory, followed by a synchronization
# script. It supports optional reset and no-sync features, and allows for
# specific account updates via the --account option. The reset feature
# clears each target directory before downloading new content, safely renaming
# the directory to ensure data integrity if the download fails. The no-sync
# feature skips the synchronization step, allowing for faster updates when
# synchronization is not needed. Configuration is managed through a file named
# 'insta_update.conf', specifying necessary settings. The script is intended
# for POSIX-compliant shell environments.
#
# Author: id774 (More info: http://id774.net)
# Source Code: https://github.com/id774/scripts
# License: LGPLv3 (Details: https://www.gnu.org/licenses/lgpl-3.0.html)
# Contact: [email protected]
#
# Version History:
# v2.0 2024-10-23
# Improved removal of trailing slashes and backslashes for
# the --account option in insta_update.sh.
# Added 'sed' to the list of required commands in the check_commands function
# to ensure the script checks for its availability before execution.
# v1.9 2024-08-19
# Fixed issue where --account option was not working when include_accounts.txt was present.
# Added logic to prioritize --account option when specified.
# v1.8 2024-07-22
# Added feature to ignore lines starting with '#'
# in include_accounts.txt and exclude_accounts.txt as comments.
# v1.7 2024-07-17
# Updated processing order to follow include_accounts.txt as listed.
# Ensured consistent variable scoping throughout the script.
# v1.6 2024-06-15
# Added --help option to display help message.
# v1.5 2024-05-04
# Handle trailing slashes in --account option by removing them.
# v1.4 2024-04-25
# Added --account option to specify a single account for updating.
# v1.3 2024-03-21
# Introduced the --no-sync (-n) option to skip the synchronization step.
# v1.2 2024-02-23
# Added check_commands function to verify the presence and executability
# of required system commands before proceeding with the main script.
# v1.1 2024-02-21
# Updated the reset functionality to rename the target directory before
# clearing, ensuring data is not lost if the download fails.
# v1.0 2024-02-19
# Initial release.
#
# Usage:
# ./insta_update.sh [--reset] [--no-sync] [--account ACCOUNT_NAME]
# The --reset option safely renames the target directory before downloading new
# content. The original directory is only removed if the download succeeds,
# ensuring data integrity. The --no-sync (-n) option skips the synchronization
# step, useful for faster updates when synchronization is not needed. The
# --account option allows for updating a specific account only.
#
# Configuration file ('insta_update.conf') requirements:
# - PYTHON_BIN: Path to the Python binary.
# - DOWNLOADER_SCRIPT: Path to the Instagram downloader script.
# - SYNC_SCRIPT: Path to the Instagram synchronization script (optional with --no-sync).
# - TARGET_DIR: Directory containing Instagram subdirectories.
# Ensure all these variables are set in 'insta_update.conf'.
#
# Notes:
# - Ensure 'exclude_accounts.txt' and 'include_accounts.txt' are properly
# formatted, with one account name per line, if they are used.
# - The script supports 'exclude_accounts.txt' and 'include_accounts.txt' lists.
# If 'exclude_accounts.txt' is present, any subdirectories matching the names
# in this list will be skipped. If 'include_accounts.txt' is present, only the
# subdirectories listed will be processed. If a subdirectory is listed in both,
# it will be excluded.
# - Lines starting with '#' in 'exclude_accounts.txt'
# and 'include_accounts.txt' are treated as comments and ignored.
#
# Error Conditions:
# 1. Configuration file not found or incomplete: The script will terminate if
# it cannot find 'insta_update.conf' or if any required variables are unset.
# 2. Unknown command-line options: If any unrecognized options are provided,
# the script will display an error message and exit.
# 3. Necessary configuration variables not set: The script checks if all
# necessary configuration variables are set in 'insta_update.conf'.
# 4. Specified scripts or target directory do not exist or are not executable.
# 126. Required command(s) not executable.
# 127. Required command(s) not installed.
#
########################################################################
# Define a function to trim and ignore comments
trim_and_ignore_comments() {
echo "$1" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | grep -v '^#'
}
show_help() {
cat << EOF
Usage: ${0##*/} [--reset] [--no-sync] [--account ACCOUNT_NAME] [--help]
This script navigates to a specified directory and executes an Instagram
content downloader script in each subdirectory, followed by a synchronization
script.
Options:
--reset Safely renames the target directory before downloading new content.
The original directory is only removed if the download succeeds,
ensuring data integrity.
--no-sync, -n Skips the synchronization step, useful for faster updates when synchronization is not needed.
--account, -a ACCOUNT_NAME
Allows for updating a specific account only.
--help, -h Display this help and exit.
Configuration file ('insta_update.conf') requirements:
- PYTHON_BIN: Path to the Python binary.
- DOWNLOADER_SCRIPT: Path to the Instagram downloader script.
- SYNC_SCRIPT: Path to the Instagram synchronization script (optional with --no-sync).
- TARGET_DIR: Directory containing Instagram subdirectories.
Ensure all these variables are set in 'insta_update.conf'.
Notes:
- Ensure 'exclude_accounts.txt' and 'include_accounts.txt' are properly
formatted, with one account name per line, if they are used.
- The script supports 'exclude_accounts.txt' and 'include_accounts.txt' lists.
If 'exclude_accounts.txt' is present, any subdirectories matching the names
in this list will be skipped. If 'include_accounts.txt' is present, only the
subdirectories listed will be processed. If a subdirectory is listed in both,
it will be excluded.
- Lines starting with '#' in 'exclude_accounts.txt'
and 'include_accounts.txt' are treated as comments and ignored.
Error Conditions:
1. Configuration file not found or incomplete: The script will terminate if
it cannot find 'insta_update.conf' or if any required variables are unset.
2. Unknown command-line options: If any unrecognized options are provided,
the script will display an error message and exit.
3. Necessary configuration variables not set: The script checks if all
necessary configuration variables are set in 'insta_update.conf'.
4. Specified scripts or target directory do not exist or are not executable.
126. Required command(s) not executable.
127. Required command(s) not installed.
EOF
}
# Determine the script's directory
SCRIPT_DIR=$(dirname "$0")
# Load configuration from a .conf file
CONF_FILE="$SCRIPT_DIR/etc/insta_update.conf"
if [ ! -f "$CONF_FILE" ]; then
CONF_FILE="$SCRIPT_DIR/../etc/insta_update.conf"
if [ ! -f "$CONF_FILE" ]; then
echo "Error: Configuration file not found."
exit 1
fi
fi
. "$CONF_FILE"
# Check if necessary variables are set
if [ -z "$PYTHON_BIN" ] || [ -z "$DOWNLOADER_SCRIPT" ] || [ -z "$SYNC_SCRIPT" ] || [ -z "$TARGET_DIR" ]; then
echo "Error: One or more configuration variables are not set. Please check your insta_update.conf."
exit 3
fi
# Check if specified scripts and target directory exist and are executable
if [ ! -x "$PYTHON_BIN" ] || [ ! -f "$DOWNLOADER_SCRIPT" ] || [ ! -x "$DOWNLOADER_SCRIPT" ] || [ ! -f "$SYNC_SCRIPT" ] || [ ! -x "$SYNC_SCRIPT" ] || [ ! -d "$TARGET_DIR" ]; then
echo "Error: Specified scripts or target directory do not exist or are not executable."
exit 4
fi
# Check for required commands
check_commands() {
for cmd in "$@"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "Error: Command '$cmd' is not installed. Please install $cmd and try again."
exit 127
elif ! [ -x "$(command -v "$cmd")" ]; then
echo "Error: Command '$cmd' is not executable. Please check the permissions."
exit 126
fi
done
}
# Ensure necessary commands are available
check_commands mv mkdir rm grep sed
RESET=false
NO_SYNC=false
ACCOUNT_SPECIFIED=""
EXCLUDE_LIST="$TARGET_DIR/exclude_accounts.txt"
INCLUDE_LIST="$TARGET_DIR/include_accounts.txt"
# Parse options
while [ $# -gt 0 ]; do
case $1 in
--reset)
RESET=true
shift
;;
--no-sync|-n)
NO_SYNC=true
shift
;;
--account|-a)
if [ -n "$2" ]; then
# Remove trailing slash, if any
ACCOUNT_SPECIFIED=$(echo "$2" | sed 's:[/\\]*$::')
shift 2
else
echo "Error: --account option requires a value."
exit 2
fi
;;
--help|-h)
show_help
exit 0
;;
*)
# Unknown option
echo "Error: Unknown option $1"
exit 2
;;
esac
done
update_content() {
subdir="$1"
if [ "$RESET" = true ]; then
echo "Resetting directory: $subdir"
subdir_basename=$(basename "$subdir") # Extract the directory name
old_dir="${TARGET_DIR}/${subdir_basename}_old"
if [ -d "$old_dir" ]; then
echo "Removing existing backup directory: ${subdir_basename}_old"
rm -rf "$old_dir" # Remove existing backup directory if it exists
fi
mv "$subdir" "$old_dir" # Rename the directory to *_old
mkdir -p "$subdir" # Create a new directory with the original name
fi
echo "Running: $PYTHON_BIN $DOWNLOADER_SCRIPT in $subdir"
cd "$subdir" || exit
"$PYTHON_BIN" "$DOWNLOADER_SCRIPT" || exit
cd "$TARGET_DIR" || exit
if [ "$NO_SYNC" = false ]; then
echo "Synchronizing: $SYNC_SCRIPT $(basename "$subdir")"
"$SYNC_SCRIPT" "$(basename "$subdir")" || exit
fi
}
should_process() {
local subdir_name=$(basename "$1")
# If an account is specified in the command line, process only that account
if [ -n "$ACCOUNT_SPECIFIED" ]; then
if [ "$subdir_name" = "$ACCOUNT_SPECIFIED" ]; then
return 0 # Process this directory
else
return 1 # Skip this directory
fi
fi
# Skip if subdir is in exclude list
if [ -f "$EXCLUDE_LIST" ]; then
while IFS= read -r line; do
line=$(trim_and_ignore_comments "$line")
if [ -n "$line" ] && [ "$line" = "$subdir_name" ]; then
return 1
fi
done < "$EXCLUDE_LIST"
fi
# Process if subdir is in include list
if [ -f "$INCLUDE_LIST" ]; then
while IFS= read -r line; do
line=$(trim_and_ignore_comments "$line")
if [ -n "$line" ] && [ "$line" = "$subdir_name" ]; then
return 0
fi
done < "$INCLUDE_LIST"
return 1 # Skip if subdir is not in include list
fi
return 0 # Default to process if no include list is provided and no account is specified
}
cd "$TARGET_DIR" || exit
# Check if include_accounts.txt exists and process in the order listed
if [ -n "$ACCOUNT_SPECIFIED" ]; then
subdir="${ACCOUNT_SPECIFIED}/"
if [ -d "$subdir" ] && should_process "$subdir"; then
update_content "$subdir"
fi
elif [ -f "$INCLUDE_LIST" ]; then
while IFS= read -r account; do
account=$(trim_and_ignore_comments "$account")
if [ -n "$account" ]; then
subdir="${account}/"
if [ -d "$subdir" ] && should_process "$subdir"; then
update_content "$subdir"
fi
fi
done < "$INCLUDE_LIST"
else
for subdir in */ ; do
if [ -d "$subdir" ] && should_process "$subdir"; then
update_content "$subdir"
fi
done
fi