Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions kindlefetch/bin/downloads/lgli_download.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ lgli_download() {
return 1
fi

local book_info="$(awk -v i="$index" 'BEGIN{RS="\\{"; FS="\\}"} NR==i+1{print $1}' "$TMP_DIR"/search_results.json)"
if [ -z "$book_info" ]; then
echo "Invalid book selection"
local book_info="$(select_preferred_format_book_info "$index" "lgli")"
if [ $? -ne 0 ] || [ -z "$book_info" ]; then
echo "No EPUB/PDF version available from LibGen for this title."
return 1
fi

local md5="$(get_json_value "$book_info" "md5")"
local title="$(get_json_value "$book_info" "title")"
local format="$(get_json_value "$book_info" "format")"
local format="$(get_json_value "$book_info" "format" | tr '[:upper:]' '[:lower:]')"

printf "\nDownloading: $title"

Expand Down Expand Up @@ -87,4 +87,4 @@ lgli_download() {
printf '\nDownload failed.' >&2
return 1
fi
}
}
61 changes: 55 additions & 6 deletions kindlefetch/bin/downloads/zlib_download.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,41 @@ zlib_download() {
return 1
fi

local book_info="$(awk -v i="$index" 'BEGIN{RS="\\{"; FS="\\}"} NR==i+1{print $1}' "$TMP_DIR"/search_results.json)"
if [ -z "$book_info" ]; then
echo "Invalid book selection" >&2
local book_info="$(select_preferred_format_book_info "$index" "zlib")"
if [ $? -ne 0 ] || [ -z "$book_info" ]; then
echo "No EPUB/PDF version available from Z-Library for this title." >&2
return 1
fi

local md5="$(get_json_value "$book_info" "md5")"
local book_page=""

local final_url="$(curl -s -L -o /dev/null -w "%{url_effective}" "$ZLIB_URL/md5/$md5")"

local book_id="$(echo "$final_url" | sed -n 's#.*/book/\([0-9][0-9]*\)/[a-z0-9]\+#\1#p')"
local book_hash="$(echo "$final_url" | sed -n 's#.*/book/[0-9][0-9]*/\([a-z0-9]\+\).*#\1#p')"
# Legacy: /book/<id>/<hash>
local book_id="$(echo "$final_url" | sed -n 's#.*/book/\([0-9][0-9]*\)/[[:alnum:]]\+\(/.*\)\?$#\1#p')"
local book_hash="$(echo "$final_url" | sed -n 's#.*/book/[0-9][0-9]*/\([[:alnum:]]\+\)\(/.*\)\?$#\1#p')"

# Current format: /book/<hash>
if [ -z "$book_hash" ]; then
book_hash="$(echo "$final_url" | sed -n 's#.*/book/\([[:alnum:]]\+\)\(/.*\)\?$#\1#p')"
fi

if [ -n "$book_hash" ]; then
book_page="$(curl -s -L -b "$ZLIB_COOKIES_FILE" "$ZLIB_URL/book/$book_hash")"
if echo "$book_page" | grep -qi "isn't available for download due to the complaint of the copyright holder"; then
echo "This title is currently unavailable on Z-Library (copyright complaint)." >&2
return 1
fi
fi

# If URL does not contain numeric id, fetch page and extract it.
if [ -z "$book_id" ] && [ -n "$book_hash" ]; then
book_id="$(echo "$book_page" | sed -n 's/.*data-book_id="\([0-9][0-9]*\)".*/\1/p' | head -n1)"
if [ -z "$book_id" ]; then
book_id="$(echo "$book_page" | sed -n 's/.*CurrentBook = new Book({\"id\":\([0-9][0-9]*\).*/\1/p' | head -n1)"
fi
fi

if [ -z "$book_id" ] || [ -z "$book_hash" ]; then
echo "Failed to extract book info from URL: $final_url" >&2
Expand All @@ -35,6 +58,31 @@ zlib_download() {
local title="$(get_json_value "$response" "description" | tr -d '\r\n')"
local ext="$(get_json_value "$response" "extension" | tr -d '\r\n')"

if [ -z "$title" ] || [ "$title" = "null" ]; then
title="$(get_json_value "$book_info" "title" | tr -d '\r\n')"
fi

if [ -z "$ext" ] || [ "$ext" = "null" ]; then
ext="$(get_json_value "$book_info" "format" | tr '[:upper:]' '[:lower:]' | tr -d '\r\n')"
fi

if [ -z "$ddl" ]; then
if [ -z "$book_page" ] || ! echo "$book_page" | grep -q "addDownloadedBook"; then
book_page="$(curl -s -L -b "$ZLIB_COOKIES_FILE" "$ZLIB_URL/book/$book_hash")"
fi
local dl_path="$(echo "$book_page" | sed -n 's#.*class="btn btn-default addDownloadedBook" href="\([^"]*\)".*#\1#p' | head -n1)"
if [ -n "$dl_path" ]; then
case "$dl_path" in
http://*|https://*)
ddl="$dl_path"
;;
*)
ddl="$ZLIB_URL$dl_path"
;;
esac
fi
fi

if [ -z "$ddl" ]; then
echo "Failed to get download link from Z-Library response." >&2
echo "$response" | head -n1
Expand All @@ -56,6 +104,7 @@ zlib_download() {
fi

local file_size="$(curl -sI "$ddl" | awk '/Content-Length/ {printf "%.2f MB\n", $2/1048576}')"
[ -z "$ext" ] && ext="bin"
local filename="$(sanitize_filename "${title}.${ext}")"
local filename="${filename:-book.bin}"

Expand Down Expand Up @@ -92,4 +141,4 @@ zlib_download() {
echo "Download failed." >&2
return 1
fi
}
}
122 changes: 116 additions & 6 deletions kindlefetch/bin/misc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ sanitize_filename() {
echo "$1" | sed -e 's/[^[:alnum:]\._-]/_/g' -e 's/ /_/g'
}

normalize_title() {
echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^[:alnum:]]//g'
}

get_json_value() {
echo "$1" | grep -o "\"$2\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" | sed "s/\"$2\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\"/\1/" || \
echo "$1" | grep -o "\"$2\"[[:space:]]*:[[:space:]]*[^,}]*" | sed "s/\"$2\"[[:space:]]*:[[:space:]]*\([^,}]*\)/\1/"
Expand Down Expand Up @@ -131,14 +135,120 @@ zlib_login() {

find_working_url() {
for url in "$@"; do
code=$(curl -s -o /dev/null -w '%{http_code}' \
--max-time 2 -L "$url")
attempt=1
while [ "$attempt" -le 5 ]; do
code=$(curl -s -o /dev/null -w '%{http_code}' \
--max-time 10 -L "$url")
curl_status=$?

if [ "$curl_status" -eq 0 ] && [ "$code" != "000" ] && [ "$code" -lt 500 ]; then
echo "$url"
return 0
fi

attempt=$((attempt + 1))
[ "$attempt" -le 5 ] && sleep 1
done
done
return 1
}

zlib_md5_is_downloadable() {
local md5="$1"
local cache_file="${TMP_DIR}/zlib_availability.cache"
local cached_status=""
local final_url=""
local book_hash=""
local book_page=""

[ -z "$md5" ] && return 0

if [ -f "$cache_file" ]; then
cached_status="$(awk -F'|' -v m="$md5" '$1 == m {print $2; exit}' "$cache_file")"
case "$cached_status" in
ok) return 0 ;;
blocked) return 1 ;;
esac
fi

[ "$code" = "000" ] && continue
[ "$code" -ge 500 ] && continue
final_url="$(curl -s -L -o /dev/null -w "%{url_effective}" "$ZLIB_URL/md5/$md5")"
book_hash="$(echo "$final_url" | sed -n 's#.*/book/\([[:alnum:]]\+\)\(/.*\)\?$#\1#p')"

echo "$url"
if [ -z "$book_hash" ]; then
echo "$md5|ok" >> "$cache_file"
return 0
fi

if [ -f "$ZLIB_COOKIES_FILE" ]; then
book_page="$(curl -s -L -b "$ZLIB_COOKIES_FILE" "$ZLIB_URL/book/$book_hash")"
else
book_page="$(curl -s -L "$ZLIB_URL/book/$book_hash")"
fi

if echo "$book_page" | grep -qi "isn't available for download due to the complaint of the copyright holder"; then
echo "$md5|blocked" >> "$cache_file"
return 1
fi

echo "$md5|ok" >> "$cache_file"
return 0
}

select_preferred_format_book_info() {
local index="$1"
local provider="$2"

if [ ! -f "$TMP_DIR/search_results.json" ]; then
return 1
fi

local selected_book_info="$(awk -v i="$index" 'BEGIN{RS="\\{"; FS="\\}"} NR==i+1{print $1}' "$TMP_DIR"/search_results.json)"
if [ -z "$selected_book_info" ]; then
return 1
fi

local selected_title="$(get_json_value "$selected_book_info" "title")"
local selected_key="$(normalize_title "$selected_title")"

local total_books="$(grep -o '"title":' "$TMP_DIR"/search_results.json | wc -l)"
local preferred_pdf=""
local i=1

while [ "$i" -le "$total_books" ]; do
local candidate="$(awk -v i="$i" 'BEGIN{RS="\\{"; FS="\\}"} NR==i+1{print $1}' "$TMP_DIR"/search_results.json)"
if [ -n "$candidate" ]; then
local candidate_description="$(get_json_value "$candidate" "description" | tr '[:upper:]' '[:lower:]')"
if echo "$candidate_description" | grep -q "$provider"; then
local candidate_title="$(get_json_value "$candidate" "title")"
local candidate_key="$(normalize_title "$candidate_title")"
if [ "$candidate_key" = "$selected_key" ]; then
local candidate_md5="$(get_json_value "$candidate" "md5")"
if [ "$provider" = "zlib" ]; then
if ! zlib_md5_is_downloadable "$candidate_md5"; then
i=$((i + 1))
continue
fi
fi
local candidate_format="$(get_json_value "$candidate" "format" | tr '[:upper:]' '[:lower:]')"
case "$candidate_format" in
epub)
echo "$candidate"
return 0
;;
pdf)
[ -z "$preferred_pdf" ] && preferred_pdf="$candidate"
;;
esac
fi
fi
fi
i=$((i + 1))
done

if [ -n "$preferred_pdf" ]; then
echo "$preferred_pdf"
return 0
fi

return 1
}
}
15 changes: 12 additions & 3 deletions kindlefetch/bin/search.sh
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ search_books() {
gsub(/"/, "\\\"", author)
gsub(/"/, "\\\"", description)

if (title != "") {
format_lc = tolower(format)
if (title != "" && (format_lc == "epub" || format_lc == "pdf")) {
if (count > 0) {
printf ",\n"
}
Expand Down Expand Up @@ -274,12 +275,18 @@ search_books() {

local lgli_available=false
local zlib_available=false
local zlib_unavailable_note=false

if echo "$book_info" | grep -q "lgli"; then
lgli_available=true
fi
if echo "$book_info" | grep -q "zlib"; then
zlib_available=true
if select_preferred_format_book_info "$choice" "zlib" >/dev/null; then
zlib_available=true
else
zlib_available=false
zlib_unavailable_note=true
fi
fi

while true; do
Expand All @@ -296,6 +303,8 @@ search_books() {
else
echo "2. zlib (Authentication required)"
fi
elif [ "$zlib_unavailable_note" = true ]; then
echo " zlib unavailable for this title (blocked or no EPUB/PDF copy)"
fi
echo "3. Cancel download"

Expand Down Expand Up @@ -394,4 +403,4 @@ search_books() {
;;
esac
done
}
}