Compare commits
52 commits
537e018647
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f600541ab | - | |
|
|
4748def178 | - | |
|
|
3e76fc49b0 | ||
|
|
665e356842 | ||
|
|
9b013d9996 | ||
|
|
34529d3372 | ||
|
|
42bf72e127 | ||
|
|
0ec24ecaf2 | ||
|
|
ee40a3b439 | ||
|
|
f897c8c2a5 | ||
|
|
93dd385cbe | ||
|
|
7da917274b | ||
|
|
ac4da0bab7 | ||
|
|
c84085236d | ||
|
|
3ea5fcfa15 | ||
|
|
5d9436d92c | ||
|
|
596426e5a8 | ||
|
|
ceb331eb10 | ||
|
|
cebc024117 | ||
|
|
5eaa4863f7 | ||
|
|
2f71885690 | ||
|
|
713fbbb29a | ||
|
|
20f311b7d6 | ||
|
|
4bbeec2230 | ||
|
|
904aa642e1 | ||
|
|
2ec3e333e5 | ||
|
|
006ecbe7d4 | ||
|
|
96e65508d1 | ||
|
|
8ebb5071a4 | ||
|
|
ebbc407b93 | ||
|
|
834ba85b30 | ||
|
|
f363327a34 | ||
|
|
3c1060a84f | ||
|
|
085b8ea8bb | ||
|
|
a43d991a3b | ||
|
|
e4bce4beef | ||
|
|
66c2231a15 | ||
|
|
e7f2320b82 | ||
|
|
194b6b672d | ||
|
|
0b438f91ba | ||
|
|
0c351f42ae | ||
|
|
755cd36fb6 | ||
|
|
b6f5334011 | ||
|
|
c29fa867f3 | ||
|
|
926df11f34 | ||
|
|
92efe6f85b | ||
|
|
4a236a56cf | ||
|
|
bb075ed369 | ||
|
|
9515d2c952 | ||
|
|
c6a2961ba3 | - | |
|
|
262e6916a9 | ||
|
|
9599a76490 |
6 changed files with 238 additions and 60 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
archives/
|
||||||
|
previews/
|
||||||
|
|
@ -5,3 +5,7 @@ An upcoming project. This will be a single program that fully automates the cont
|
||||||
It will be written in a mixture of Bash and Python. Tails and Whonix will be supported, with the goal of making the program work natively in Tails without the need to install additional software.
|
It will be written in a mixture of Bash and Python. Tails and Whonix will be supported, with the goal of making the program work natively in Tails without the need to install additional software.
|
||||||
|
|
||||||
Anyone is welcome to collaborate with me.
|
Anyone is welcome to collaborate with me.
|
||||||
|
|
||||||
|
## Collaborators
|
||||||
|
|
||||||
|
Currently it is not possible to submit pull requests when using the Tor Browser on the Safest setting. Please do not fork this repo attempting to submit a pull request. Instead leave a comment in [this thread](http://onion.tor.my/PedoDeveloper/autoshare/issues/7) and you will be added as a collaborator
|
||||||
|
|
|
||||||
43
includes/functions.sh
Normal file
43
includes/functions.sh
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Common utility functions shared across multiple files.
|
||||||
|
|
||||||
|
RESET="\033[0m"
|
||||||
|
GREEN="\033[1;32m"
|
||||||
|
YELLOW="\033[1;33m"
|
||||||
|
RED="\033[1;31m"
|
||||||
|
|
||||||
|
check_dependencies() {
|
||||||
|
# Usage: check_dependencies "7z" "unrar" "curl" ...
|
||||||
|
local dependencies=()
|
||||||
|
local dependency
|
||||||
|
|
||||||
|
for dependency in "$@"; do
|
||||||
|
if ! command -v "$dependency" >/dev/null; then
|
||||||
|
dependencies+=("$dependency")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if (( "${#dependencies[@]}" > 0 )); then
|
||||||
|
log "ERROR" "Missing dependencies" "${dependencies[@]}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
log() {
|
||||||
|
# Usage: log "NOTICE|WARN|ERROR" "this is a log message" ...
|
||||||
|
local caller="${0##*/}"
|
||||||
|
local level="$1"; shift
|
||||||
|
local color
|
||||||
|
|
||||||
|
case "$level" in
|
||||||
|
NOTICE) color="$GREEN" ;;
|
||||||
|
WARN) color="$YELLOW" ;;
|
||||||
|
ERROR) color="$RED" ;;
|
||||||
|
|
||||||
|
# No color for these levels.
|
||||||
|
INFO) color="" ;;
|
||||||
|
*) color="" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo -e "$caller: ${color}[$level]: $*${RESET}" >&2
|
||||||
|
}
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
archive_dir="$(dirname "$0")/../archives"
|
|
||||||
|
|
||||||
input_file="${1}"
|
|
||||||
archive_pwd="${2}"
|
|
||||||
size="$3"
|
|
||||||
|
|
||||||
check_dependencies() {
|
|
||||||
if ! mkdir -p "$archive_dir"; then
|
|
||||||
echo "ERROR: Unable to create archive directory"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v 7z 2>&1 >/dev/null; then
|
|
||||||
echo "ERROR: 7z must be installed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
check_input() {
|
|
||||||
if [[ ! -e "${input_file}" ]]; then
|
|
||||||
echo "ERROR: Input file '${input_file}' does not exist"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Archiving file/directory '${input_file}'" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
set_volumes() {
|
|
||||||
volumes=
|
|
||||||
|
|
||||||
if [[ "$size" =~ ^[1-9][0-9]*$ ]]; then
|
|
||||||
volumes="-v${size}m"
|
|
||||||
elif [[ -n "$size" ]]; then
|
|
||||||
echo "Invalid size $size, must be a number"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Volumes set to '$volumes'" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_name() {
|
|
||||||
archive="$archive_dir/$(base64 /dev/urandom | tr -dc [:alnum:] | head -c 20).7z"
|
|
||||||
|
|
||||||
echo "Generated archive name $archive" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
create_archive() {
|
|
||||||
echo "Packing ${input_file} into archive $archive with password ${archive_pwd}"
|
|
||||||
[[ -n "$volumes" ]] && echo "and volumes of size $size MB"
|
|
||||||
|
|
||||||
7z a -mhe=on "-p${archive_pwd}" "$volumes" "$archive" "${input_file}" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
check_dependencies
|
|
||||||
check_input
|
|
||||||
set_volumes
|
|
||||||
generate_name
|
|
||||||
create_archive
|
|
||||||
116
modules/create_archive
Executable file
116
modules/create_archive
Executable file
|
|
@ -0,0 +1,116 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# This script packs a file or directory into a 7z archive with the given password.
|
||||||
|
# It can (optionally) split the archives into volumes of a fixed size in megabytes.
|
||||||
|
|
||||||
|
source "$(dirname "$0")/../includes/functions.sh"
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
local archive_name="$1"
|
||||||
|
rm -f "${archive_name}"*
|
||||||
|
log "INFO" "Cleaning up ${archive_name##*/} remains before exit"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_input() {
|
||||||
|
local input_file="$1"
|
||||||
|
local password="$2"
|
||||||
|
local size="$3"
|
||||||
|
|
||||||
|
[[ -e "$input_file" ]] || { log "ERROR" "Input file '${input_file}' does not exist"; exit 2; }
|
||||||
|
[[ -n "${password}" ]] || { log "ERROR" "No password given"; exit 2; }
|
||||||
|
[[ "$size" =~ ^([1-9][0-9]*)?$ ]] || { log "ERROR" "Invalid size '$size', must be empty or a positive number"; exit 2; }
|
||||||
|
}
|
||||||
|
|
||||||
|
calc_smart_volumes() {
|
||||||
|
# Calculates a "smart" volume size so that each volume (including the final part)
|
||||||
|
# will be approximately the same size
|
||||||
|
local input_file="$1"
|
||||||
|
local size="$2"
|
||||||
|
local total_size num_volumes smart_size
|
||||||
|
|
||||||
|
total_size=$(du -s -BM "${input_file}" | grep -oP '^\d+') || return 1
|
||||||
|
|
||||||
|
# If total file size is smaller than volume size, don't pack it into volumes
|
||||||
|
if (( total_size < size)); then
|
||||||
|
log "WARN" "$input_file is smaller than ${size}MB, skipping volumes"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
num_volumes=$(( (total_size + size - 1) / size ))
|
||||||
|
smart_size=$(( (total_size + num_volumes - 1) / num_volumes ))
|
||||||
|
|
||||||
|
log "INFO" "Calculated smart volume size '$smart_size'"
|
||||||
|
|
||||||
|
echo "$smart_size"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_volumes() {
|
||||||
|
local input_file="$1"
|
||||||
|
local size="${2:-}"
|
||||||
|
local volumes=""
|
||||||
|
local smart_size=""
|
||||||
|
|
||||||
|
if [[ -n "$size" ]]; then
|
||||||
|
log "INFO" "Volumes size is set to ${size}MB"
|
||||||
|
smart_size="$(calc_smart_volumes "$input_file" "$size" || true)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$smart_size" ]]; then
|
||||||
|
volumes="-v${smart_size}m"
|
||||||
|
log "INFO" "Volumes set to '$volumes'"
|
||||||
|
else
|
||||||
|
log "INFO" "Volumes argument unset"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$volumes"
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_name() {
|
||||||
|
# Generates a random archive name of 20 alphanumeric characters
|
||||||
|
local archive_dir="$1"
|
||||||
|
local archive_name
|
||||||
|
archive_name="$archive_dir/$(tr -dc '[:alnum:]' < /dev/urandom | head -c 20).7z"
|
||||||
|
|
||||||
|
log "INFO" "Generated archive name '$archive_name'"
|
||||||
|
|
||||||
|
echo "$archive_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
create_archive() {
|
||||||
|
local input_file="$1"
|
||||||
|
local password="$2"
|
||||||
|
local volumes="$3"
|
||||||
|
local archive_name="$4"
|
||||||
|
|
||||||
|
7z a -mhe=on "-p${password}" "$volumes" "$archive_name" "${input_file}"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local input_file="${1:-}"
|
||||||
|
local password="${2:-}"
|
||||||
|
local size="${3:-}"
|
||||||
|
local volumes archive_name archive_dir
|
||||||
|
|
||||||
|
check_dependencies "7z"
|
||||||
|
check_input "$input_file" "$password" "$size"
|
||||||
|
|
||||||
|
archive_dir="$(dirname "$0")/../archives"
|
||||||
|
mkdir -p "$archive_dir"
|
||||||
|
|
||||||
|
archive_name="$(generate_name "$archive_dir")"
|
||||||
|
volumes="$(get_volumes "$input_file" "$size")"
|
||||||
|
|
||||||
|
log "INFO" "Packing '${input_file}' into archive '$archive_name' with password '${password}'"
|
||||||
|
|
||||||
|
trap 'cleanup "$archive_name"' ERR INT
|
||||||
|
create_archive \
|
||||||
|
"$input_file" \
|
||||||
|
"$password" \
|
||||||
|
"$volumes" \
|
||||||
|
"$archive_name"
|
||||||
|
|
||||||
|
log "NOTICE" "Archive created"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
73
modules/create_video_previews
Executable file
73
modules/create_video_previews
Executable file
|
|
@ -0,0 +1,73 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
preview_dir="$(dirname "$0")/../previews"
|
||||||
|
|
||||||
|
search_dir="${1}"
|
||||||
|
|
||||||
|
check_dependencies() {
|
||||||
|
if ! mkdir -p "$preview_dir"; then
|
||||||
|
echo "ERROR: Unable to create preview directory"
|
||||||
|
exit 1
|
||||||
|
elif ! command -v ffmpeg xargs 2>&1 >/dev/null; then
|
||||||
|
echo "ERROR: FFmpeg and xargs must be installed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_input() {
|
||||||
|
if [[ ! -e "${search_dir}" ]]; then
|
||||||
|
echo "ERROR: Input file '${search_dir}' does not exist"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Search for videos recursively using the MIME type
|
||||||
|
find_videos() {
|
||||||
|
video_list=$(find ${search_dir} -type f -print0 | xargs -0 file -i | grep -oP '.*(?=:\s+video/)')
|
||||||
|
|
||||||
|
echo "${video_list}" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
create_previews() {
|
||||||
|
while IFS= read -r video; do
|
||||||
|
echo "Making preview for ${video}"
|
||||||
|
make_preview
|
||||||
|
done <<< "${video_list}"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_size() {
|
||||||
|
IFS=','
|
||||||
|
read -r width height <<< $(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 "${video}")
|
||||||
|
|
||||||
|
if (( $width >= $height )); then
|
||||||
|
rows=4 cols=5
|
||||||
|
scale_format="200:-1"
|
||||||
|
else
|
||||||
|
rows=5 cols=4
|
||||||
|
scale_format="-1:200"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_num_frames() {
|
||||||
|
local num_snapshots=$(( rows * cols ))
|
||||||
|
|
||||||
|
num_frames=$(ffprobe -v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -of csv=p=0 "${video}")
|
||||||
|
echo "Num frames: $num_frames" >&2
|
||||||
|
|
||||||
|
frames_per_snapshot=$(( num_frames / num_snapshots ))
|
||||||
|
}
|
||||||
|
|
||||||
|
make_preview() {
|
||||||
|
get_size
|
||||||
|
get_num_frames
|
||||||
|
|
||||||
|
filename="$preview_dir/$(basename "${video}").webp"
|
||||||
|
filters="select=not(mod(n\,$frames_per_snapshot)),scale=$scale_format,tile=${rows}x${cols}"
|
||||||
|
|
||||||
|
ffmpeg -nostdin -loglevel panic -i "${video}" -frames 1 -q:v 90 -vf "$filters" "${filename}"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_dependencies
|
||||||
|
check_input
|
||||||
|
find_videos
|
||||||
|
create_previews
|
||||||
Loading…
Add table
Add a link
Reference in a new issue