├── .gitignore ├── LICENSE ├── README.md ├── create_release.sh ├── install.sh └── kindlefetch ├── bin ├── downloads │ ├── lgli_download.sh │ └── zlib_download.sh ├── filters.sh ├── kindlefetch.sh ├── link_config ├── local_books.sh ├── misc.sh ├── search.sh ├── settings.sh ├── setup.sh └── update.sh ├── config.xml ├── menu.json └── run.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | books/ 3 | .env 4 | kindlefetch_config 5 | .vscode 6 | .idea 7 | venv/ 8 | kindlefetch.zip 9 | .version -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 justrals 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # KindleFetch 4 | 5 | 6 | 7 | 8 | Simple CLI for downloading books directly to your Kindle without a computer. 9 | 10 | ## Prerequisites 11 | **Your Kindle must be jailbroken before proceeding!** 12 | If it's not, follow [this guide](https://kindlemodding.org/) first. 13 | 14 | **Install kterm**: 15 | 1. Download the latest release from [kterm's releases page](https://github.com/bfabiszewski/kterm/releases) 16 | 2. Unzip the archive to the `extensions` directory in your Kindle's root 17 | 18 | **KOReader (Optional but Recommended):** 19 | 20 | 1. **Download** the latest release from the [KOReader Releases Page](https://github.com/koreader/koreader/releases) 21 | 2. **Unsure which version to get?** Check the [Installation Guide](https://github.com/koreader/koreader/wiki/Installation-on-Kindle-devices#err-there-are-four-kindle-packages-to-choose-from-which-do-i-pick) 22 | 3. **Extract** the contents of the downloaded archive to the **root directory** of your Kindle 23 | 24 | ## Installation 25 | 26 | ### Automatic installation (Recomended) 27 | 28 | 1. **Launch KUAL** (Kindle Unified Application Launcher) and open **kterm** 29 | 30 | 2. **Run the installation command** in kterm: 31 | ```bash 32 | curl https://justrals.github.io/KindleFetch/install.sh | sh 33 | ``` 34 | 35 | 3. **Complete the setup**: 36 | - Wait for the installation to finish (you should see a success message) 37 | - Type `exit` to close kterm 38 | - You should now see a new "KindleFetch" option in KUAL 39 | 40 | ### Manual Installation 41 | 42 | 1. **Download** the latest release from the [**Releases**](https://github.com/justrals/KindleFetch/releases) tab 43 | 44 | 2. **Unzip** it and move its contents into the `extensions` folder in the root directory of your **Kindle** 45 | - You should now see a new "KindleFetch" option in KUAL 46 | 47 | 3. Update from the main menu if asked 48 | -------------------------------------------------------------------------------- /create_release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | rm kindlefetch.zip 3 | 4 | get_version() { 5 | api_response=$(curl -s -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/justrals/KindleFetch/commits") || { 6 | echo "Warning: Failed to fetch version from GitHub API" >&2 7 | echo "unknown" 8 | return 9 | } 10 | 11 | latest_sha=$(echo "$api_response" | grep -m1 '"sha":' | cut -d'"' -f4 | cut -c1-7) 12 | 13 | if [ -n "$latest_sha" ]; then 14 | echo "${latest_sha}" 15 | fi 16 | } 17 | 18 | VERSION=$(get_version) 19 | mkdir -p "$INSTALL_DIR/bin" 20 | echo "$VERSION" > "kindlefetch/bin/.version" 21 | 22 | find kindlefetch -name ".DS_Store" -delete 23 | 24 | zip kindlefetch.zip -r kindlefetch -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | # Check if running on a Kindle 6 | if ! { [ -f "/etc/prettyversion.txt" ] || [ -d "/mnt/us" ] || pgrep "lipc-daemon" >/dev/null; }; then 7 | echo "Error: This script must run on a Kindle device." >&2 8 | exit 1 9 | fi 10 | 11 | # Variables 12 | API_URL="https://api.github.com/repos/justrals/KindleFetch/commits" 13 | REPO_URL="https://github.com/justrals/KindleFetch/archive/refs/heads/main.zip" 14 | ZIP_FILE="/mnt/us/repo.zip" 15 | EXTRACTED_DIR="/mnt/us/KindleFetch-main" 16 | INSTALL_DIR="/mnt/us/extensions/kindlefetch" 17 | CONFIG_FILE="$INSTALL_DIR/bin/kindlefetch_config" 18 | VERSION_FILE="$INSTALL_DIR/bin/.version" 19 | TEMP_CONFIG="/mnt/us/kindlefetch_config_backup" 20 | 21 | get_version() { 22 | api_response=$(curl -s -H "Accept: application/vnd.github.v3+json" "$API_URL") || { 23 | echo "Warning: Failed to fetch version from GitHub API" >&2 24 | echo "unknown" 25 | return 26 | } 27 | 28 | latest_sha=$(echo "$api_response" | grep -m1 '"sha":' | cut -d'"' -f4 | cut -c1-7) 29 | 30 | if [ -n "$latest_sha" ]; then 31 | echo "${latest_sha}" 32 | fi 33 | } 34 | 35 | if [ -f "$CONFIG_FILE" ]; then 36 | echo "Backing up existing config..." 37 | cp -f "$CONFIG_FILE" "$TEMP_CONFIG" 38 | fi 39 | 40 | echo "Downloading KindleFetch..." 41 | curl -s -L -o "$ZIP_FILE" "$REPO_URL" 42 | echo "Download complete." 43 | 44 | echo "Extracting files..." 45 | unzip -o "$ZIP_FILE" -d "/mnt/us" 46 | echo "Extraction complete." 47 | rm -f "$ZIP_FILE" 48 | 49 | echo "Removing old installation..." 50 | rm -rf "$INSTALL_DIR" 51 | 52 | echo "Installing KindleFetch..." 53 | mkdir -p "$INSTALL_DIR" 54 | mv -f "$EXTRACTED_DIR/kindlefetch"/* "$INSTALL_DIR/" 55 | echo "Installation successful." 56 | 57 | echo "Creating version file..." 58 | VERSION=$(get_version) 59 | mkdir -p "$INSTALL_DIR/bin" 60 | echo "$VERSION" > "$VERSION_FILE" 61 | 62 | if [ -f "$TEMP_CONFIG" ]; then 63 | echo "Restoring configuration..." 64 | mv -f "$TEMP_CONFIG" "$CONFIG_FILE" 65 | fi 66 | 67 | echo "Cleaning up..." 68 | rm -rf "$EXTRACTED_DIR" 69 | 70 | echo "KindleFetch installation completed successfully. Version: $VERSION" -------------------------------------------------------------------------------- /kindlefetch/bin/downloads/lgli_download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | lgli_download() { 4 | local index=$1 5 | 6 | if [ ! -f "/tmp/search_results.json" ]; then 7 | echo "Error: No search results found" >&2 8 | return 1 9 | fi 10 | 11 | local book_info=$(awk -v i="$index" 'BEGIN{RS="\\{"; FS="\\}"} NR==i+1{print $1}' /tmp/search_results.json) 12 | if [ -z "$book_info" ]; then 13 | echo "Error: Invalid book selection" >&2 14 | return 1 15 | fi 16 | 17 | local md5=$(get_json_value "$book_info" "md5") 18 | local title=$(get_json_value "$book_info" "title") 19 | local format=$(get_json_value "$book_info" "format") 20 | 21 | echo "Downloading: $title" 22 | 23 | local clean_title=$(sanitize_filename "$title" | tr -d ' ') 24 | local final_location 25 | 26 | echo -n "Do you want to change filename? [y/N] " 27 | read confirm 28 | if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then 29 | echo -n "Enter your custom filename: " 30 | read custom_filename 31 | if [ -n "$custom_filename" ]; then 32 | local clean_title=$(sanitize_filename "$custom_filename" | tr -d ' ') 33 | else 34 | echo "Invalid filename. Proceeding with original filename." 35 | fi 36 | else 37 | echo "Proceeding with original filename." 38 | fi 39 | 40 | if [ ! -w "$KINDLE_DOCUMENTS" ]; then 41 | echo "Error: No write permission in $KINDLE_DOCUMENTS" >&2 42 | return 1 43 | fi 44 | 45 | if [ "$CREATE_SUBFOLDERS" = "true" ]; then 46 | local book_folder="$KINDLE_DOCUMENTS/$clean_title" 47 | if ! mkdir -p "$book_folder"; then 48 | echo "Error: Failed to create folder '$book_folder'" >&2 49 | return 1 50 | fi 51 | final_location="$book_folder/$clean_title.$format" 52 | else 53 | final_location="$KINDLE_DOCUMENTS/$clean_title.$format" 54 | fi 55 | 56 | if [ -e "$final_location" ] && [ ! -w "$final_location" ]; then 57 | echo "Error: No permission to overwrite $final_location" >&2 58 | return 1 59 | fi 60 | 61 | echo "Fetching download page..." 62 | if ! lgli_content=$(curl -s -L "$LGLI_URL/ads.php?md5=$md5"); then 63 | if ! lgli_content=$(curl -s -L -x "$PROXY_URL" "$LGLI_URL/ads.php?md5=$md5"); then 64 | echo "Error: Failed to fetch book page" >&2 65 | return 1 66 | fi 67 | fi 68 | 69 | if ! download_link=$(echo "$lgli_content" | grep -o -m 1 'href="[^"]*get\.php[^"]*"' | cut -d'"' -f2); then 70 | echo "Error: Failed to parse download link" >&2 71 | return 1 72 | fi 73 | 74 | if [ -z "$download_link" ]; then 75 | echo "Error: No download link found" >&2 76 | return 1 77 | fi 78 | 79 | local download_url="$LGLI_URL/$download_link" 80 | echo "Downloading from: $download_url" 81 | 82 | echo "Progress:" 83 | 84 | for retry in 1 2 3; do 85 | if curl -# -L -o "$final_location" "$download_url"; then 86 | echo "Download successful!" 87 | echo "Saved to: $final_location" 88 | return 0 89 | else 90 | if curl -x "$PROXY_URL" -# -L -o "$final_location" "$download_url"; then 91 | echo "Download successful!" 92 | echo "Saved to: $final_location" 93 | return 0 94 | else 95 | echo "Download attempt $retry failed" 96 | [ $retry -lt 3 ] && sleep 5 97 | fi 98 | fi 99 | done 100 | 101 | echo "Error: Failed to download after 3 attempts" >&2 102 | return 1 103 | } -------------------------------------------------------------------------------- /kindlefetch/bin/downloads/zlib_download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | zlib_download() { 4 | local index=$1 5 | 6 | if [ ! -f "/tmp/search_results.json" ]; then 7 | echo "Error: No search results found" >&2 8 | return 1 9 | fi 10 | 11 | local book_info=$(awk -v i="$index" 'BEGIN{RS="\\{"; FS="\\}"} NR==i+1{print $1}' /tmp/search_results.json) 12 | if [ -z "$book_info" ]; then 13 | echo "Error: Invalid book selection" >&2 14 | return 1 15 | fi 16 | 17 | local md5=$(get_json_value "$book_info" "md5") 18 | local title=$(get_json_value "$book_info" "title") 19 | local format=$(get_json_value "$book_info" "format") 20 | 21 | echo "Downloading: $title" 22 | 23 | local clean_title=$(sanitize_filename "$title" | tr -d ' ') 24 | local final_location 25 | 26 | echo -n "Do you want to change filename? [y/N] " 27 | read confirm 28 | if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then 29 | echo -n "Enter your custom filename: " 30 | read custom_filename 31 | if [ -n "$custom_filename" ]; then 32 | local clean_title=$(sanitize_filename "$custom_filename" | tr -d ' ') 33 | else 34 | echo "Invalid filename. Proceeding with original filename." 35 | fi 36 | else 37 | echo "Proceeding with original filename." 38 | fi 39 | 40 | if [ ! -w "$KINDLE_DOCUMENTS" ]; then 41 | echo "Error: No write permission in $KINDLE_DOCUMENTS" >&2 42 | return 1 43 | fi 44 | 45 | if [ "$CREATE_SUBFOLDERS" = "true" ]; then 46 | local book_folder="$KINDLE_DOCUMENTS/$clean_title" 47 | if ! mkdir -p "$book_folder"; then 48 | echo "Error: Failed to create folder '$book_folder'" >&2 49 | return 1 50 | fi 51 | final_location="$book_folder/$clean_title.$format" 52 | else 53 | final_location="$KINDLE_DOCUMENTS/$clean_title.$format" 54 | fi 55 | 56 | if [ -e "$final_location" ] && [ ! -w "$final_location" ]; then 57 | echo "Error: No permission to overwrite $final_location" >&2 58 | return 1 59 | fi 60 | 61 | echo "Fetching download page..." 62 | if ! zlib_content=$(curl -s -L "$ZLIB_URL/md5/$md5"); then 63 | if ! zlib_content=$(curl -s -L -x "$PROXY_URL" "$ZLIB_URL/md5/$md5"); then 64 | echo "Error: Failed to fetch book page" >&2 65 | return 1 66 | fi 67 | fi 68 | 69 | if ! download_link=$(echo "$zlib_content" | grep -o 'href="/dl/[^"]*"' | head -1 | sed 's/href="//;s/"//'); then 70 | echo "Error: Failed to parse download link" >&2 71 | return 1 72 | fi 73 | 74 | if [ -z "$download_link" ]; then 75 | echo "Error: No download link found" >&2 76 | return 1 77 | fi 78 | 79 | local download_url="$ZLIB_URL$download_link" 80 | echo "Downloading from: $download_url" 81 | 82 | echo "Progress:" 83 | 84 | for retry in 1 2 3; do 85 | if curl -# -L -o "$final_location" "$download_url"; then 86 | echo "Download successful!" 87 | echo "Saved to: $final_location" 88 | return 0 89 | else 90 | if curl -x "$PROXY_URL" -# -L -o "$final_location" "$download_url"; then 91 | echo "Download successful!" 92 | echo "Saved to: $final_location" 93 | return 0 94 | else 95 | echo "Download attempt $retry failed" 96 | [ $retry -lt 3 ] && sleep 5 97 | fi 98 | fi 99 | done 100 | 101 | echo "Error: Failed to download after 3 attempts" >&2 102 | return 1 103 | } -------------------------------------------------------------------------------- /kindlefetch/bin/filters.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | filters_menu() { 4 | CURRENT_FILTERS_FILE="$SCRIPT_DIR/tmp/current_filters" 5 | CURRENT_PARAMS_FILE="$SCRIPT_DIR/tmp/current_filter_params" 6 | 7 | current_tab=1 8 | total_tabs=5 9 | 10 | mkdir -p "$SCRIPT_DIR/tmp" 2>/dev/null 11 | 12 | if [ -f "$CURRENT_FILTERS_FILE" ]; then 13 | . "$CURRENT_FILTERS_FILE" 2>/dev/null || { 14 | content_filter="" 15 | ext_filter="" 16 | lang_filter="" 17 | src_filter="" 18 | sort_filter="" 19 | } 20 | else 21 | content_filter="" 22 | ext_filter="" 23 | lang_filter="" 24 | src_filter="" 25 | sort_filter="" 26 | fi 27 | 28 | while true; do 29 | clear 30 | echo -e " 31 | ______ _ _ _ 32 | | ____(_) | | 33 | | |__ _| | |_ ___ _ __ ___ 34 | | __| | | | __/ _ \\ '__/ __| 35 | | | | | | || __/ | \\__ \\ 36 | |_| |_|_|\\__\\___|_| |___/ 37 | " 38 | echo "╭──────────────────────────────────────╮" 39 | echo "│ 1. Content 2. Format 3. Language │" 40 | echo "│ 4. Source 5. Sort │" 41 | echo "│ Enter - Apply & Exit │" 42 | echo "╰──────────────────────────────────────╯" 43 | echo "" 44 | 45 | echo "Active Filters:" 46 | [ -n "$content_filter" ] && echo " content: $content_filter" 47 | [ -n "$ext_filter" ] && echo " ext: $ext_filter" 48 | [ -n "$lang_filter" ] && echo " lang: $lang_filter" 49 | [ -n "$src_filter" ] && echo " src: $src_filter" 50 | [ -n "$sort_filter" ] && echo " sort: $sort_filter" 51 | echo "" 52 | 53 | case $current_tab in 54 | 1) echo "── CONTENT TYPE ────────────────────────" 55 | echo "1) Nonfiction 5) Comic" 56 | echo "2) Fiction 6) Standards" 57 | echo "3) Unknown 7) Other" 58 | echo "4) Magazine 8) Musical Score" 59 | echo "" 60 | echo "0) Clear Filter" ;; 61 | 2) echo "── FILE FORMAT ────────────────────────" 62 | echo "1) PDF 5) CBR" 63 | echo "2) EPUB 6) DJVU" 64 | echo "3) MOBI 7) CBZ" 65 | echo "4) FB2 8) TXT 9) AZW3" 66 | echo "" 67 | echo "0) Clear Filter" ;; 68 | 3) echo "── LANGUAGE ───────────────────────────" 69 | echo "1) English (en) 4) German (de)" 70 | echo "2) Russian (ru) 5) French (fr)" 71 | echo "3) Spanish (es) 6) Custom Input" 72 | echo "" 73 | echo "0) Clear Filter" ;; 74 | 4) echo "── SOURCE ────────────────────────────" 75 | echo "1) Library Genesis (lgli)" 76 | echo "2) Z-Library (zlib)" 77 | echo "" 78 | echo "0) Clear Filter" ;; 79 | 5) echo "── SORT BY ───────────────────────────" 80 | echo "1) Newest 5) Newest Added" 81 | echo "2) Oldest 6) Oldest Added" 82 | echo "3) Largest 7) Random" 83 | echo "4) Smallest 8) Most Relevant" 84 | echo "" 85 | echo "0) Clear Filter" ;; 86 | esac 87 | 88 | echo "" 89 | echo -n "Choose option (or t[1-5] to switch tabs): " 90 | read choice 91 | 92 | case "$choice" in 93 | t1|t2|t3|t4|t5) current_tab=${choice#t} ;; 94 | 0) case $current_tab in 95 | 1) content_filter="" ;; 96 | 2) ext_filter="" ;; 97 | 3) lang_filter="" ;; 98 | 4) src_filter="" ;; 99 | 5) sort_filter="" ;; 100 | esac ;; 101 | [1-9]) 102 | case $current_tab in 103 | 1) case $choice in 104 | 1) content_filter="book_nonfiction" ;; 105 | 2) content_filter="book_fiction" ;; 106 | 3) content_filter="book_unknown" ;; 107 | 4) content_filter="magazine" ;; 108 | 5) content_filter="book_comic" ;; 109 | 6) content_filter="standards_document" ;; 110 | 7) content_filter="other" ;; 111 | 8) content_filter="musical_score" ;; 112 | esac ;; 113 | 2) case $choice in 114 | 1) ext_filter="pdf" ;; 115 | 2) ext_filter="epub" ;; 116 | 3) ext_filter="mobi" ;; 117 | 4) ext_filter="fb2" ;; 118 | 5) ext_filter="cbr" ;; 119 | 6) ext_filter="djvu" ;; 120 | 7) ext_filter="cbz" ;; 121 | 8) ext_filter="txt" ;; 122 | 9) ext_filter="azw3" ;; 123 | esac ;; 124 | 3) case $choice in 125 | 1) lang_filter="en" ;; 126 | 2) lang_filter="ru" ;; 127 | 3) lang_filter="es" ;; 128 | 4) lang_filter="de" ;; 129 | 5) lang_filter="fr" ;; 130 | 6) echo -n "Enter language code: " 131 | read lang_code 132 | lang_filter="$lang_code" ;; 133 | esac ;; 134 | 4) case $choice in 135 | 1) src_filter="lgli" ;; 136 | 2) src_filter="zlib" ;; 137 | esac ;; 138 | 5) case $choice in 139 | 1) sort_filter="newest" ;; 140 | 2) sort_filter="oldest" ;; 141 | 3) sort_filter="largest" ;; 142 | 4) sort_filter="smallest" ;; 143 | 5) sort_filter="newest_added" ;; 144 | 6) sort_filter="oldest_added" ;; 145 | 7) sort_filter="random" ;; 146 | 8) sort_filter="" ;; 147 | esac ;; 148 | esac ;; 149 | "") 150 | { 151 | echo "content_filter=\"$content_filter\"" 152 | echo "ext_filter=\"$ext_filter\"" 153 | echo "lang_filter=\"$lang_filter\"" 154 | echo "src_filter=\"$src_filter\"" 155 | echo "sort_filter=\"$sort_filter\"" 156 | } > "$CURRENT_FILTERS_FILE" 157 | 158 | filter_string="" 159 | [ -n "$content_filter" ] && filter_string="${filter_string}&content=$content_filter" 160 | [ -n "$ext_filter" ] && filter_string="${filter_string}&ext=$ext_filter" 161 | [ -n "$lang_filter" ] && filter_string="${filter_string}&lang=$lang_filter" 162 | [ -n "$src_filter" ] && filter_string="${filter_string}&src=$src_filter" 163 | [ -n "$sort_filter" ] && filter_string="${filter_string}&sort=$sort_filter" 164 | echo "$filter_string" > "$CURRENT_PARAMS_FILE" 165 | 166 | return 0 167 | ;; 168 | *) echo "Invalid option"; sleep 1 ;; 169 | esac 170 | done 171 | } -------------------------------------------------------------------------------- /kindlefetch/bin/kindlefetch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # KindleFetch 4 | # Made by justrals 5 | # https://github.com/justrals/KindleFetch 6 | 7 | # Variables 8 | SCRIPT_DIR=$(dirname "$(readlink -f "$0")") 9 | CONFIG_FILE="$SCRIPT_DIR/kindlefetch_config" 10 | LINK_CONFIG_FILE="$SCRIPT_DIR/link_config" 11 | VERSION_FILE="$SCRIPT_DIR/.version" 12 | 13 | UPDATE_AVAILABLE=false 14 | 15 | # Check if running on a Kindle 16 | if ! { [ -f "/etc/prettyversion.txt" ] || [ -d "/mnt/us" ] || pgrep "lipc-daemon" >/dev/null; }; then 17 | echo "Error: This script must run on a Kindle device." >&2 18 | echo "Press any key to exit." 19 | read -n 1 -s 20 | exit 1 21 | fi 22 | 23 | # Script imports 24 | . "$SCRIPT_DIR/downloads/zlib_download.sh" 25 | . "$SCRIPT_DIR/downloads/lgli_download.sh" 26 | . "$SCRIPT_DIR/filters.sh" 27 | . "$SCRIPT_DIR/search.sh" 28 | . "$SCRIPT_DIR/misc.sh" 29 | . "$SCRIPT_DIR/local_books.sh" 30 | . "$SCRIPT_DIR/update.sh" 31 | . "$SCRIPT_DIR/setup.sh" 32 | . "$SCRIPT_DIR/settings.sh" 33 | 34 | main_menu() { 35 | load_config 36 | check_for_updates 37 | 38 | while true; do 39 | clear 40 | echo -e " 41 | _ ___ _ _ ______ _ _ 42 | | |/ (_) | | | | ____| | | | | 43 | | ' / _ _ __ __| | | ___| |__ ___| |_ ___| |__ 44 | | < | | '_ \ / _\` | |/ _ \ __/ _ \ __/ __| '_ \\ 45 | | . \| | | | | (_| | | __/ | | __/ || (__| | | | 46 | |_|\_\_|_| |_|\__,_|_|\___|_| \___|\__\___|_| |_| 47 | 48 | $(load_version) | https://github.com/justrals/KindleFetch 49 | " 50 | if $UPDATE_AVAILABLE; then 51 | echo "Update available! Select option 6 to install." 52 | echo "" 53 | fi 54 | echo "1. Search and download books" 55 | echo "2. Filter search results" 56 | echo "3. List my books" 57 | echo "4. Settings" 58 | echo "5. Exit" 59 | if $UPDATE_AVAILABLE; then 60 | echo "" 61 | echo "6. Install update" 62 | fi 63 | echo "" 64 | echo -n "Choose option: " 65 | read choice 66 | 67 | case "$choice" in 68 | 1) 69 | search_books 70 | ;; 71 | 2) 72 | filters_menu 73 | ;; 74 | 3) 75 | list_local_books 76 | ;; 77 | 4) 78 | settings_menu 79 | ;; 80 | 5) 81 | cleanup 82 | exit 0 83 | ;; 84 | 6) 85 | if $UPDATE_AVAILABLE; then 86 | update 87 | fi 88 | ;; 89 | *) 90 | echo "Invalid option" 91 | sleep 2 92 | ;; 93 | esac 94 | done 95 | } 96 | 97 | trap cleanup EXIT 98 | main_menu -------------------------------------------------------------------------------- /kindlefetch/bin/link_config: -------------------------------------------------------------------------------- 1 | QU5OQVNfVVJMPSJodHRwczovL2FubmFzLWFyY2hpdmUub3JnIgpMR0xJX1VSTD0iaHR0cHM6Ly9saWJnZW4ubGkiClpMSUJfVVJMPSJodHRwczovL3otbGliLmZtIgpQUk9YWV9VUkw9Imh0dHA6Ly9pZGsuanVzdHJhbHMudGVjaDozMTI4Ig== -------------------------------------------------------------------------------- /kindlefetch/bin/local_books.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | delete_book() { 4 | index=$1 5 | book_file=$(sed -n "${index}p" /tmp/kindle_books.list 2>/dev/null) 6 | 7 | if [ -z "$book_file" ]; then 8 | echo "Invalid selection" 9 | return 1 10 | fi 11 | 12 | echo -n "Are you sure you want to delete '$book_file'? [y/N] " 13 | read confirm 14 | if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then 15 | if rm -f "$book_file"; then 16 | echo "Book deleted successfully" 17 | else 18 | echo "Failed to delete book" 19 | fi 20 | else 21 | echo "Deletion canceled" 22 | fi 23 | } 24 | 25 | delete_directory() { 26 | index=$1 27 | dir_path=$(sed -n "${index}p" /tmp/kindle_folders.list 2>/dev/null) 28 | 29 | if [ -z "$dir_path" ]; then 30 | echo "Invalid selection" 31 | return 1 32 | fi 33 | 34 | echo -n "Are you sure you want to delete '$dir_path' and all its contents? [y/N] " 35 | read confirm 36 | if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then 37 | if rm -rf "$dir_path"; then 38 | echo "Directory deleted successfully" 39 | else 40 | echo "Failed to delete directory" 41 | fi 42 | else 43 | echo "Deletion canceled" 44 | fi 45 | } 46 | 47 | list_local_books() { 48 | while true; do 49 | local current_dir="${1:-$KINDLE_DOCUMENTS}" 50 | clear 51 | echo -e " 52 | ____ _ 53 | | _ \ | | 54 | | |_) | ___ ___ | | _____ 55 | | _ < / _ \ / _ \| |/ / __| 56 | | |_) | (_) | (_) | <\__ \\ 57 | |____/ \___/ \___/|_|\_\___/ 58 | " 59 | echo "Current directory: $current_dir" 60 | echo "--------------------------------" 61 | echo "" 62 | 63 | i=1 64 | > /tmp/kindle_books.list 65 | > /tmp/kindle_folders.list 66 | 67 | if [ ! -d "$current_dir" ]; then 68 | echo "Error: Directory '$current_dir' does not exist." 69 | return 1 70 | fi 71 | 72 | for item in "$current_dir"/*; do 73 | if [ -d "$item" ]; then 74 | foldername=$(basename "$item") 75 | echo "$i. $foldername/" 76 | echo "$item" >> /tmp/kindle_folders.list 77 | i=$((i+1)) 78 | fi 79 | done 80 | 81 | for item in "$current_dir"/*; do 82 | if [ -f "$item" ]; then 83 | filename=$(basename "$item") 84 | extension="${filename##*.}" 85 | echo "$i. $filename" 86 | echo "$item" >> /tmp/kindle_books.list 87 | i=$((i+1)) 88 | fi 89 | done 90 | 91 | if [ $i -eq 1 ]; then 92 | echo "No books or folders found." 93 | return 1 94 | fi 95 | 96 | echo "" 97 | echo "--------------------------------" 98 | echo "n: Go up to parent directory" 99 | echo "d: Delete directory" 100 | echo "q: Back to main menu" 101 | echo "" 102 | 103 | total_items=$(( $(wc -l < /tmp/kindle_folders.list 2>/dev/null) + $(wc -l < /tmp/kindle_books.list 2>/dev/null) )) 104 | 105 | echo -n "Enter choice: " 106 | read choice 107 | 108 | case "$choice" in 109 | [qQ]) 110 | return 0 # Changed from break to return 111 | ;; 112 | [nN]) 113 | current_dir=$(dirname "$current_dir") 114 | ;; 115 | [dD]) 116 | echo -n "Enter directory number to delete: " 117 | read dir_num 118 | if echo "$dir_num" | grep -qE '^[0-9]+$'; then 119 | if [ "$dir_num" -le $(wc -l < /tmp/kindle_folders.list 2>/dev/null) ]; then 120 | delete_directory "$dir_num" 121 | else 122 | echo "Invalid directory number" 123 | sleep 2 124 | fi 125 | fi 126 | ;; 127 | *) 128 | if echo "$choice" | grep -qE '^[0-9]+$'; then 129 | if [ "$choice" -ge 1 ] && [ "$choice" -le "$total_items" ]; then 130 | if [ "$choice" -le $(wc -l < /tmp/kindle_folders.list 2>/dev/null) ]; then 131 | current_dir=$(sed -n "${choice}p" /tmp/kindle_folders.list) 132 | else 133 | file_index=$((choice - $(wc -l < /tmp/kindle_folders.list 2>/dev/null))) 134 | delete_book "$file_index" 135 | fi 136 | else 137 | echo "Invalid selection (must be between 1 and $total_items)" 138 | sleep 2 139 | fi 140 | else 141 | echo "Invalid input" 142 | sleep 2 143 | fi 144 | ;; 145 | esac 146 | 147 | set -- "$current_dir" 148 | done 149 | } -------------------------------------------------------------------------------- /kindlefetch/bin/misc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | load_config() { 4 | eval "$(base64 -d "$LINK_CONFIG_FILE")" 5 | if [ -f "$CONFIG_FILE" ]; then 6 | . "$CONFIG_FILE" 7 | else 8 | first_time_setup 9 | fi 10 | } 11 | 12 | load_version() { 13 | if [ -f "$VERSION_FILE" ]; then 14 | cat "$VERSION_FILE" 15 | else 16 | echo "Version file wasn't found!" 17 | sleep 2 18 | echo "Creating version file" 19 | sleep 2 20 | get_version 21 | fi 22 | } 23 | 24 | sanitize_filename() { 25 | echo "$1" | sed -e 's/[^[:alnum:]\._-]/_/g' -e 's/ /_/g' 26 | } 27 | 28 | get_json_value() { 29 | echo "$1" | grep -o "\"$2\":\"[^\"]*\"" | sed "s/\"$2\":\"\([^\"]*\)\"/\1/" || \ 30 | echo "$1" | grep -o "\"$2\":[^,}]*" | sed "s/\"$2\":\([^,}]*\)/\1/" 31 | } 32 | 33 | ensure_config_dir() { 34 | config_dir=$(dirname "$CONFIG_FILE") 35 | if [ ! -d "$config_dir" ]; then 36 | mkdir -p "$config_dir" 37 | fi 38 | } 39 | 40 | cleanup() { 41 | rm -f /tmp/kindle_books.list \ 42 | /tmp/kindle_folders.list \ 43 | /tmp/search_results.json \ 44 | /tmp/last_search_* 45 | } 46 | 47 | get_version() { 48 | api_response=$(curl -s -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/justrals/KindleFetch/commits") || { 49 | echo "Warning: Failed to fetch version from GitHub API" >&2 50 | echo "unknown" 51 | return 52 | } 53 | 54 | latest_sha=$(echo "$api_response" | grep -m1 '"sha":' | cut -d'"' -f4 | cut -c1-7) 55 | 56 | echo "$latest_sha" > "$VERSION_FILE" 57 | load_version 58 | } 59 | 60 | check_for_updates() { 61 | local current_sha=$(load_version) 62 | 63 | local latest_sha=$(curl -s -H "Accept: application/vnd.github.v3+json" \ 64 | -H "Cache-Control: no-cache" \ 65 | "https://api.github.com/repos/justrals/KindleFetch/commits?per_page=1" | \ 66 | grep -oE '"sha": "[0-9a-f]+"' | head -1 | cut -d'"' -f4 | cut -c1-7) 67 | 68 | if [ -n "$latest_sha" ] && [ "$current_sha" != "$latest_sha" ]; then 69 | UPDATE_AVAILABLE=true 70 | return 0 71 | else 72 | return 1 73 | fi 74 | } 75 | 76 | save_config() { 77 | echo "KINDLE_DOCUMENTS=\"$KINDLE_DOCUMENTS\"" > "$CONFIG_FILE" 78 | echo "CREATE_SUBFOLDERS=\"$CREATE_SUBFOLDERS\"" >> "$CONFIG_FILE" 79 | echo "DEBUG_MODE=\"$DEBUG_MODE\"" >> "$CONFIG_FILE" 80 | echo "COMPACT_OUTPUT=\"$COMPACT_OUTPUT\"" >> "$CONFIG_FILE" 81 | } -------------------------------------------------------------------------------- /kindlefetch/bin/search.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | display_books() { 4 | clear 5 | echo -e " 6 | _____ _ 7 | / ____| | | 8 | | (___ ___ __ _ _ __ ___| |__ 9 | \___ \ / _ \/ _\` | '__/ __| '_ \\ 10 | ____) | __/ (_| | | | (__| | | | 11 | |_____/ \___|\__,_|_| \___|_| |_| 12 | " 13 | echo "--------------------------------" 14 | echo "" 15 | 16 | i=$((count-1)) 17 | while [ $i -ge 0 ]; do 18 | book_info=$(echo "$1" | awk -v i=$i 'BEGIN{RS="\\{"; FS="\\}"} NR==i+2{print $1}') 19 | title=$(get_json_value "$book_info" "title") 20 | author=$(get_json_value "$book_info" "author") 21 | format=$(get_json_value "$book_info" "format") 22 | description=$(get_json_value "$book_info" "description") 23 | 24 | if ! $COMPACT_OUTPUT; then 25 | printf "%2d. %s\n" $((i+1)) "$title" 26 | [ -n "$description" ] && [ "$description" != "null" ] && echo " $description" 27 | echo "" 28 | else 29 | printf "%2d. %s by %s in %s format\n" $((i+1)) "$title" "$author" "$format" 30 | # [ -n "$description" ] && [ "$description" != "null" ] && echo " $description" 31 | echo "" 32 | fi 33 | 34 | i=$((i-1)) 35 | done 36 | 37 | echo "--------------------------------" 38 | echo "" 39 | echo "Page $2 of $5" 40 | echo "" 41 | 42 | if [ "$3" = "true" ]; then 43 | echo -n "p: Previous page | " 44 | fi 45 | if [ "$4" = "true" ]; then 46 | echo -n "n: Next page | " 47 | fi 48 | echo "1-$count: Select book | q: Quit" 49 | echo "" 50 | } 51 | 52 | search_books() { 53 | local query="$1" 54 | local page="${2:-1}" 55 | 56 | if [ -z "$query" ]; then 57 | echo -n "Enter search query: " 58 | read query 59 | [ -z "$query" ] && { 60 | echo "Search query cannot be empty" 61 | return 1 62 | } 63 | fi 64 | 65 | echo "Searching for '$query' (page $page)..." 66 | 67 | local filters="" 68 | if [ -f "$SCRIPT_DIR"/tmp/current_filter_params ]; then 69 | filters=$(cat "$SCRIPT_DIR/tmp/current_filter_params") 70 | fi 71 | 72 | encoded_query=$(echo "$query" | sed 's/ /+/g') 73 | search_url="$ANNAS_URL/search?page=${page}&q=${encoded_query}${filters}" 74 | local html_content=$(curl -s "$search_url") || html_content=$(curl -s -x "$PROXY_URL" "$search_url") 75 | 76 | local last_page=$(echo "$html_content" | grep -o 'page=[0-9]\+"' | sort -nr | head -1 | cut -d= -f2 | tr -d '"') 77 | [ -z "$last_page" ] && last_page=1 78 | 79 | local has_prev="false" 80 | [ "$page" -gt 1 ] && has_prev="true" 81 | 82 | local has_next="false" 83 | [ "$page" -lt "$last_page" ] && has_next="true" 84 | 85 | echo "$query" > /tmp/last_search_query 86 | echo "$page" > /tmp/last_search_page 87 | echo "$last_page" > /tmp/last_search_last_page 88 | echo "$has_next" > /tmp/last_search_has_next 89 | echo "$has_prev" > /tmp/last_search_has_prev 90 | 91 | local books=$(echo "$html_content" | awk ' 92 | BEGIN { 93 | RS="
"; 94 | FS=">"; 95 | print "[" 96 | book_count = 0 97 | } 98 | NR > 1 { 99 | link = ""; md5 = ""; title = ""; author = ""; format = "null"; description = "null" 100 | 101 | # Extract MD5 and link 102 | if ($0 ~ / 0) { 106 | link = substr($0, link_start, link_end - 1) 107 | md5 = substr(link, 6, 32) 108 | } 109 | } 110 | 111 | # Extract title 112 | if ($0 ~ /

") + 1 116 | title_end = index(title_part, "

") 117 | if (title_end > 0) { 118 | title = substr(title_part, title_start, title_end - title_start) 119 | gsub(/^[[:space:]]+|[[:space:]]+$/, "", title) 120 | gsub(/"/, "\\\"", title) 121 | gsub(/•/, "\\u2022", title) 122 | } 123 | } 124 | 125 | # Extract author 126 | if ($0 ~ /
") + 1 130 | author_end = index(author_part, "
") 131 | if (author_end > 0) { 132 | author = substr(author_part, author_start, author_end - author_start) 133 | gsub(/^[[:space:]]+|[[:space:]]+$/, "", author) 134 | gsub(/"/, "\\\"", author) 135 | } 136 | } 137 | 138 | # Extract format 139 | if ($0 ~ /text-gray-500">/) { 140 | format_start = index($0, "text-gray-500\">") + 15 141 | format_part = substr($0, format_start) 142 | format_end = index(format_part, "<") 143 | if (format_end > 0) { 144 | format_line = substr(format_part, 1, format_end - 1) 145 | if (match(format_line, /\.([a-z0-9]+),/)) { 146 | format = substr(format_line, RSTART + 1, RLENGTH - 2) 147 | format = "\"" format "\"" 148 | } 149 | } 150 | } 151 | 152 | # Extract description 153 | if ($0 ~ /class="[^"]*text-gray-500[^"]*"/) { 154 | desc_start = index($0, "text-gray-500") 155 | desc_part = substr($0, desc_start) 156 | desc_start = index(desc_part, ">") + 1 157 | desc_end = index(desc_part, "
") 158 | if (desc_end > 0) { 159 | description = substr(desc_part, desc_start, desc_end - desc_start) 160 | gsub(/^[[:space:]]+|[[:space:]]+$/, "", description) 161 | gsub(/"/, "\\\"", description) 162 | description = "\"" description "\"" 163 | } 164 | } 165 | 166 | gsub(/🚀/, "Partner Server", description) 167 | gsub(/📗|📘|📕|📰|💬|📝|🤨|🎶|✅/, "", description) 168 | 169 | if (title != "") { 170 | if (book_count > 0) printf ",\n" 171 | printf " {\"author\":\"%s\",\"format\":%s,\"md5\":\"%s\",\"title\":\"%s\",\"url\":\"$ANNAS_URL%s\",\"description\":%s}", 172 | author, format, md5, title, link, description 173 | book_count++ 174 | } 175 | } 176 | END { print "\n]" } 177 | ') 178 | 179 | echo "$books" > /tmp/search_results.json 180 | 181 | while true; do 182 | query=$(cat /tmp/last_search_query 2>/dev/null) 183 | current_page=$(cat /tmp/last_search_page 2>/dev/null || echo 1) 184 | last_page=$(cat /tmp/last_search_last_page 2>/dev/null || echo 1) 185 | has_next=$(cat /tmp/last_search_has_next 2>/dev/null || echo "false") 186 | has_prev=$(cat /tmp/last_search_has_prev 2>/dev/null || echo "false") 187 | books=$(cat /tmp/search_results.json 2>/dev/null) 188 | count=$(echo "$books" | grep -o '"title":' | wc -l) 189 | 190 | display_books "$books" "$current_page" "$has_prev" "$has_next" "$last_page" 191 | 192 | echo -n "Enter choice: " 193 | read choice 194 | 195 | case "$choice" in 196 | [qQ]) 197 | break 198 | ;; 199 | [pP]) 200 | if [ "$has_prev" = "true" ]; then 201 | new_page=$((current_page - 1)) 202 | search_books "$query" "$new_page" 203 | else 204 | echo "Already on first page" 205 | sleep 2 206 | fi 207 | ;; 208 | [nN]) 209 | if [ "$has_next" = "true" ]; then 210 | new_page=$((current_page + 1)) 211 | search_books "$query" "$new_page" 212 | else 213 | echo "Already on last page" 214 | sleep 2 215 | fi 216 | ;; 217 | *) 218 | if echo "$choice" | grep -qE '^[0-9]+$'; then 219 | if [ "$choice" -ge 1 ] && [ "$choice" -le "$count" ]; then 220 | local book_info=$(awk -v i="$choice" 'BEGIN{RS="\\{"; FS="\\}"} NR==i+1{print $1}' /tmp/search_results.json) 221 | 222 | local lgli_available=false 223 | local zlib_available=false 224 | 225 | if echo "$book_info" | grep -q "lgli"; then 226 | local lgli_available=true 227 | fi 228 | if echo "$book_info" | grep -q "zlib"; then 229 | local zlib_available=true 230 | fi 231 | 232 | if [ "$lgli_available" = false ] && [ "$zlib_available" = false ]; then 233 | echo "There are no available sources for this book right now. :[" 234 | fi 235 | 236 | if [ "$lgli_available" = true ]; then 237 | echo "1. lgli" 238 | fi 239 | if [ "$zlib_available" = true ]; then 240 | echo "2. zlib" 241 | fi 242 | echo "3. Cancel download" 243 | 244 | while true; do 245 | echo -n "Choose source to proceed with: " 246 | read source_choice 247 | 248 | case "$source_choice" in 249 | 1) 250 | if [ "$lgli_available" = true ]; then 251 | echo "Proceeding with lgli..." 252 | if ! lgli_download "$choice"; then 253 | echo "Download from lgli failed." 254 | sleep 2 255 | else 256 | break 257 | fi 258 | else 259 | echo "Invalid choice." 260 | fi 261 | ;; 262 | 2) 263 | if [ "$zlib_available" = true ]; then 264 | echo "Proceeding with zlib..." 265 | if ! zlib_download "$choice"; then 266 | echo "Download from zlib failed." 267 | sleep 2 268 | else 269 | break 270 | fi 271 | else 272 | echo "Invalid choice." 273 | fi 274 | ;; 275 | 3) 276 | break 277 | ;; 278 | *) 279 | echo "Invalid choice." 280 | ;; 281 | esac 282 | done 283 | 284 | echo -n "Press any key to continue..." 285 | read -n 1 -s 286 | else 287 | echo "Invalid selection (must be between 1 and $count)" 288 | sleep 2 289 | fi 290 | else 291 | echo "Invalid input" 292 | sleep 2 293 | fi 294 | ;; 295 | esac 296 | done 297 | } -------------------------------------------------------------------------------- /kindlefetch/bin/settings.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | settings_menu() { 4 | while true; do 5 | clear 6 | echo -e " 7 | _____ _ _ _ 8 | / ____| | | | | (_) 9 | | (___ ___| |_| |_ _ _ __ __ _ ___ 10 | \___ \ / _ \ __| __| | '_ \ / _\` / __| 11 | ____) | __/ |_| |_| | | | | (_| \__ \\ 12 | |_____/ \___|\__|\__|_|_| |_|\__, |___/ 13 | __/ | 14 | |___/ 15 | " 16 | echo "Tip:" 17 | echo "Tap two fingers and press the X button to refresh the screen." 18 | echo "" 19 | echo "Current configuration:" 20 | echo "1. Documents directory: $KINDLE_DOCUMENTS" 21 | echo "2. Toggle subfolders for books: $CREATE_SUBFOLDERS" 22 | echo "3. Toggle compact output: $COMPACT_OUTPUT" 23 | echo "4. Check for updates" 24 | echo "5. Back to main menu" 25 | echo "" 26 | echo -n "Choose option: " 27 | read choice 28 | 29 | case "$choice" in 30 | 1) 31 | echo -n "Enter your new Kindle downloads directory [It will be /mnt/us/your_directory. Only enter your_directory part.]: " 32 | read new_dir 33 | if [ -n "$new_dir" ]; then 34 | KINDLE_DOCUMENTS="/mnt/us/$new_dir" 35 | if [ ! -d "$KINDLE_DOCUMENTS" ]; then 36 | mkdir -p "$KINDLE_DOCUMENTS" || { 37 | echo "Error: Failed to create directory $KINDLE_DOCUMENTS" >&2 38 | exit 1 39 | } 40 | fi 41 | save_config 42 | fi 43 | ;; 44 | 2) 45 | if $CREATE_SUBFOLDERS; then 46 | CREATE_SUBFOLDERS=false 47 | echo "Subfolders disabled" 48 | else 49 | CREATE_SUBFOLDERS=true 50 | echo "Subfolders enabled" 51 | fi 52 | save_config 53 | ;; 54 | 3) 55 | if $COMPACT_OUTPUT; then 56 | COMPACT_OUTPUT=false 57 | echo "Condensed output disabled" 58 | else 59 | COMPACT_OUTPUT=true 60 | echo "Condensed output enabled" 61 | fi 62 | save_config 63 | ;; 64 | 4) 65 | check_for_updates 66 | update 67 | ;; 68 | 5) 69 | break 70 | ;; 71 | 72 | *) 73 | echo "Invalid option" 74 | sleep 2 75 | ;; 76 | esac 77 | done 78 | } -------------------------------------------------------------------------------- /kindlefetch/bin/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | first_time_setup() { 4 | clear 5 | echo -e " 6 | _____ _ 7 | / ____| | | 8 | | (___ ___| |_ _ _ _ __ 9 | \___ \ / _ \ __| | | | '_ \ 10 | ____) | __/ |_| |_| | |_) | 11 | |_____/ \___|\__|\__,_| .__/ 12 | | | 13 | |_| 14 | " 15 | echo "Welcome to KindleFetch! Let's set up your configuration." 16 | echo "" 17 | echo "NOTE: This tool does not provide copyrighted material. You must configure your own book sources." 18 | echo "" 19 | 20 | echo -n "Enter your Kindle downloads directory [It will be /mnt/us/your_directory. Only enter your_directory part.]: " 21 | read user_input 22 | if [ -n "$user_input" ]; then 23 | KINDLE_DOCUMENTS="/mnt/us/$user_input" 24 | if [ ! -d "$KINDLE_DOCUMENTS" ]; then 25 | mkdir -p "$KINDLE_DOCUMENTS" || { 26 | echo "Error: Failed to create directory $KINDLE_DOCUMENTS" >&2 27 | exit 1 28 | } 29 | fi 30 | else 31 | KINDLE_DOCUMENTS="/mnt/us/documents" 32 | fi 33 | echo -n "Create subfolders for books? [y/N]: " 34 | read subfolders_choice 35 | if [ "$subfolders_choice" = "y" ] || [ "$subfolders_choice" = "Y" ]; then 36 | CREATE_SUBFOLDERS="true" 37 | else 38 | CREATE_SUBFOLDERS="false" 39 | fi 40 | echo -n "Enable compact output? [y/N]: " 41 | read compact_choice 42 | if [ "$compact_choice" = "y" ] || [ "$compact_choice" = "Y" ]; then 43 | CREATE_SUBFOLDERS="true" 44 | else 45 | COMPACT_OUTPUT="false" 46 | fi 47 | 48 | save_config 49 | . "$CONFIG_FILE" 50 | } -------------------------------------------------------------------------------- /kindlefetch/bin/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | update() { 4 | if [ "$UPDATE_AVAILABLE" = true ]; then 5 | echo -n "Would you like to update? [Y/n] " 6 | read confirm 7 | 8 | if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ] || [ -z "$confirm" ]; then 9 | echo "Installing update..." 10 | if curl -s https://justrals.github.io/KindleFetch/install.sh | sh; then 11 | echo "Update installed successfully!" 12 | UPDATE_AVAILABLE=false 13 | VERSION=$(load_version) 14 | exec exit 0 15 | else 16 | echo "Failed to install update" 17 | sleep 2 18 | fi 19 | fi 20 | else 21 | echo "You're up-to-date!" 22 | sleep 2 23 | fi 24 | } -------------------------------------------------------------------------------- /kindlefetch/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | KindleFetch 5 | 1.0 6 | justrals 7 | kindlefetch 8 | 9 | 10 | menu.json 11 | 12 | 13 | -------------------------------------------------------------------------------- /kindlefetch/menu.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | {"name": "KindleFetch", "action": "sh run.sh"} 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /kindlefetch/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | /mnt/us/extensions/kterm/bin/kterm -e "bash /mnt/us/extensions/kindlefetch/bin/kindlefetch.sh" -k 1 -o U -s 7 4 | --------------------------------------------------------------------------------