Last active
September 27, 2023 13:16
-
-
Save scooterpsu/9a91da3cfebe2b4754876123c198acef to your computer and use it in GitHub Desktop.
Komga to Chunky Interface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This is a thing I made to get (originally) Komga reading lists into Chunky on my iPad. | |
This can now send single issues, whole series, reading lists, or selected loose files. | |
Requirements: | |
Jailbroken iPad | |
Tweaks from Cydia (or other tweak source) - Open, cURL, Activator | |
Chunky Reader | |
Linux binaries/support - bc, ssh, jq, websocketd (https://github.com/joewalnes/websocketd) | |
Instructions: | |
Put websocketd binary with .sh files and autorun, edit for your use-case, chmod +x all the things, run autorun. | |
Edit komga.user.js for your use-case, install with Tampermonkey (might work with Firemonkey, unsure), profit. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
cd $(dirname "$0") | |
./websocketd --port=9000 ./runme.sh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Send to iPad Button | |
// @namespace http://tampermonkey.net/ | |
// @version 1.1 | |
// @description websocketd buttons for Komga | |
// @author scooterpsu | |
// @include http://192.168.1.110:8099/* | |
// @grant none | |
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js | |
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js | |
// @require https://code.jquery.com/ui/1.11.4/jquery-ui.min.js | |
// ==/UserScript== | |
/* globals $, waitForKeyElements */ | |
var websocket = "ws://192.168.1.110:9000/?type="; | |
var ipadButton = $('<div class="col col-auto"><a class="tmelement v-btn v-btn--is-elevated v-btn--has-bg v-size--small" id="ipadButton" target="_blank"><span class="v-btn__content"><i aria-hidden="true" class="v-icon notranslate v-icon--left mdi mdi-tablet-android" style="font-size: 16px"></i> Send To iPad </span></a></div>'); | |
var overlay = $('<div class="tmelement container v-toolbar v-sheet" id="logContainer" style="position:fixed; z-index: 10; margin: auto; left:0; right: 0; top: 0; bottom:0; width:60%; height:60%;padding:0;min-height:415px;"><header class="v-sheet v-toolbar base"><div class="v-toolbar__content"><span style="flex-grow:0; margin-right:14px;" class="v-btn__content"><i aria-hidden="true" class="v-icon notranslate mdi mdi-tablet-android"></i></span><div class="v-toolbar__title"><span>Sending to iPad</span></div><span id="counter" class="tmelement mx-4 v-chip v-chip--label v-chip--no-color v-size--default" style="display:none;"><span id="counterText" class="v-chip__content"><span style="font-size: 1.1rem;"></span></span></span><div class="spacer"></div><button type="button" class="v-btn v-btn--icon v-btn--round v-size--default tmelement" onclick="$(\'#log\').empty();$(\'#logContainer\').remove();"><span class="v-btn__content"><i aria-hidden="true" class="v-icon notranslate mdi mdi-close"></i><span class="v-tooltip v-tooltip--bottom"></span></span></button></div></header><div style="width:100%; height:5px;background-color: var(--v-secondary-base);opacity:0.3;"></div><div id="progressbar" style="width: 100%;height:5px;margin-top:-5px;"></div><div class="row" style="margin: 0;"><div class="col-auto"><div class="tmelement v-card v-image v-responsive" style="width: 195px;"><div class="v-responsive__sizer" style="padding-bottom: 260px;"></div><div id="thumbnail" class="v-image__image v-image__image--contain" style="background-position: center center;"></div></div><div class="iosstats" style="width: 195px;margin-top: 15px;display:none;"><hr role="separator" aria-orientation="horizontal" class="v-divider tmelement" style="margin-bottom: 8px;"><span style="float: left;" class="v-btn__content"><i aria-hidden="true" class="v-icon notranslate mdi mdi-folder-information tmelement" style="font-size: 30px;margin-left:5px;margin-top:2px;"></i></span><div style="float: right;" class="body-2" id="capacity"></div><div style="float: right;"class="body-2" id="freespace"></div></div></div><div class="col" style="padding:0;max-width: calc(100% - 219px);"><pre style="overflow-y:auto;overflow-x:hidden; height:calc(60vh - 63px); padding:10px;" class="body-2" id="log"></pre></div></div></div>'); | |
var toolbarButton=$('<button type="button" id="toolbarButton" class="tmelement v-btn v-btn--icon v-btn--round v-size--default"><span class="v-btn__content"><i aria-hidden="true" class="tmelement v-icon notranslate mdi mdi-tablet-android"></i><span class="v-tooltip v-tooltip--bottom"></span></span></button>'); | |
var toolTip = $('<div id="toolTip" class="v-tooltip__content" style="z-index: 8; display: none; opacity: 1;"><span>Send to iPad</span></div>'); | |
function addReadlistButton () { | |
if(!$('#ipadButton').length){ | |
var type = "readlists"; | |
var $downloadButton = $('a[title|="Download read list"]'); | |
var id = $downloadButton[0].href.split('/file')[0].split('/').pop(); | |
$downloadButton.parent().addClass('col-auto'); | |
$downloadButton.parent().parent().append(ipadButton); | |
$('#ipadButton').attr('title','Send read list to iPad'); | |
themeButton(); | |
observer.observe($downloadButton[0], { | |
attributes: true, | |
attributeFilter: ['class'] | |
}); | |
$("#ipadButton").off("click"); | |
$('#ipadButton').on('click', function() { | |
$("#logContainer").remove(); | |
var ws = new WebSocket(websocket+type+"&id="+id); | |
ws.onopen = function() { | |
overlay.prependTo('.container:first'); | |
$("#counter").hide(); | |
$("#counterText").empty(); | |
themeButton(); | |
$('#thumbnail').css('background-image', 'url('+location.protocol+'//'+location.host+'/api/v1/readlists/'+id+'/thumbnail)'); | |
$('#progressbar').progressbar({value:0}); | |
$('.ui-progressbar-value').css('height', '100%').css('background','var(--v-secondary-base)'); | |
}; | |
ws.onclose = function() { | |
setTimeout(function(){ | |
$('#log').empty(); | |
$('#logContainer').remove(); | |
}, 5000); | |
}; | |
ws.onmessage = function(event) { | |
if (event.data.startsWith("BOOKID:")){ | |
$('#thumbnail').css('background-image', 'url('+location.protocol+'//'+location.host+'/api/v1/books/'+event.data.split("BOOKID:")[1]+'/thumbnail)'); | |
}else if (event.data.startsWith("PROGRESS:")){ | |
$('#progressbar').progressbar({value:parseFloat(event.data.split("PROGRESS:")[1])}); | |
}else if (event.data.startsWith("COUNTER:")){ | |
$('#counter').show(); | |
$('#counter > span').text(event.data.split("COUNTER:")[1]); | |
}else if (event.data.startsWith("FREESPACE:")){ | |
$('.iosstats').show(); | |
$('#freespace').text(event.data.split("FREESPACE:")[1]); | |
}else if (event.data.startsWith("TOTALSPACE:")){ | |
$('.iosstats').show(); | |
$('#capacity').text(event.data.split("TOTALSPACE:")[1]); | |
}else{ | |
log(event.data); | |
} | |
}; | |
}); | |
} | |
} | |
waitForKeyElements ("a[title|='Download read list']", addReadlistButton); | |
function addSeriesButton () { | |
if(!$('#ipadButton').length){ | |
var type = "series"; | |
var $downloadButton = $('a[title|="Download series"]'); | |
var id = $downloadButton[0].href.split('/file')[0].split('/').pop(); | |
$downloadButton.parent().parent().append(ipadButton); | |
$('#ipadButton').attr('title','Send series to iPad'); | |
themeButton(); | |
observer.observe($downloadButton[0], { | |
attributes: true, | |
attributeFilter: ['class'] | |
}); | |
$("#ipadButton").off("click"); | |
$('#ipadButton').on('click', function() { | |
$("#logContainer").remove(); | |
var ws = new WebSocket(websocket+type+"&id="+id); | |
ws.onopen = function() { | |
overlay.prependTo('.container:first'); | |
$("#counter").hide(); | |
$("#counterText").empty(); | |
themeButton(); | |
$('#thumbnail').css('background-image', 'url('+location.protocol+'//'+location.host+'/api/v1/series/'+id+'/thumbnail)'); | |
$('#progressbar').progressbar({value:0}); | |
$('.ui-progressbar-value').css('height', '100%').css('background','var(--v-secondary-base)'); | |
}; | |
ws.onclose = function() { | |
setTimeout(function(){ | |
$('#log').empty(); | |
$('#logContainer').remove(); | |
}, 5000); | |
}; | |
ws.onmessage = function(event) { | |
if (event.data.startsWith("BOOKID:")){ | |
$('#thumbnail').css('background-image', 'url('+location.protocol+'//'+location.host+'/api/v1/books/'+event.data.split("BOOKID:")[1]+'/thumbnail)'); | |
}else if (event.data.startsWith("PROGRESS:")){ | |
$('#progressbar').progressbar({value:parseFloat(event.data.split("PROGRESS:")[1])}); | |
}else if (event.data.startsWith("COUNTER:")){ | |
$('#counter').show(); | |
$('#counter > span').text(event.data.split("COUNTER:")[1]); | |
}else if (event.data.startsWith("FREESPACE:")){ | |
$('.iosstats').show(); | |
$('#freespace').text(event.data.split("FREESPACE:")[1]); | |
}else if (event.data.startsWith("TOTALSPACE:")){ | |
$('.iosstats').show(); | |
$('#capacity').text(event.data.split("TOTALSPACE:")[1]); | |
}else{ | |
log(event.data); | |
} | |
}; | |
}); | |
} | |
} | |
waitForKeyElements ("a[title|='Download series']", addSeriesButton); | |
function addFileButton () { | |
if(!$('#ipadButton').length){ | |
var type = "books"; | |
var $downloadButton = $('a[title|="Download file"]'); | |
var id = $downloadButton[0].href.split('/file')[0].split('/').pop(); | |
$downloadButton.parent().parent().append(ipadButton); | |
$('#ipadButton').attr('title','Send file to iPad'); | |
themeButton(); | |
observer.observe($downloadButton[0], { | |
attributes: true, | |
attributeFilter: ['class'] | |
}); | |
$("#ipadButton").off("click"); | |
$('#ipadButton').on('click', function() { | |
$("#logContainer").remove(); | |
var ws = new WebSocket(websocket+type+"&id="+id); | |
ws.onopen = function() { | |
overlay.prependTo('.container:first'); | |
$("#counter").hide(); | |
$("#counterText").empty(); | |
themeButton(); | |
$('#thumbnail').css('background-image', 'url('+location.protocol+'//'+location.host+'/api/v1/books/'+id+'/thumbnail)'); | |
$('#progressbar').progressbar({value:0}); | |
$('.ui-progressbar-value').css('height', '100%').css('background','var(--v-secondary-base)'); | |
}; | |
ws.onclose = function() { | |
setTimeout(function(){ | |
$('#log').empty(); | |
$('#logContainer').remove(); | |
}, 5000); | |
}; | |
ws.onmessage = function(event) { | |
if (event.data.startsWith("BOOKID:")){ | |
$('#thumbnail').css('background-image', 'url('+location.protocol+'//'+location.host+'/api/v1/books/'+event.data.split("BOOKID:")[1]+'/thumbnail)'); | |
}else if (event.data.startsWith("PROGRESS:")){ | |
$('#progressbar').progressbar({value:parseFloat(event.data.split("PROGRESS:")[1])}); | |
}else if (event.data.startsWith("COUNTER:")){ | |
$('#counter').show(); | |
$('#counter > span').text(event.data.split("COUNTER:")[1]); | |
}else if (event.data.startsWith("FREESPACE:")){ | |
$('.iosstats').show(); | |
$('#freespace').text(event.data.split("FREESPACE:")[1]); | |
}else if (event.data.startsWith("TOTALSPACE:")){ | |
$('.iosstats').show(); | |
$('#capacity').text(event.data.split("TOTALSPACE:")[1]); | |
}else{ | |
log(event.data); | |
} | |
}; | |
}); | |
} | |
} | |
waitForKeyElements ("a[title|='Download file']", addFileButton); | |
function addToolbarButton () { | |
if(!$('#toolbarButton').length){ | |
$('.v-toolbar__content > .spacer').after(toolbarButton); | |
themeButton(); | |
var $closeButton = $('.sticky-bar .mdi-close'); | |
observer.observe($closeButton[0], { | |
attributes: true, | |
attributeFilter: ['class'] | |
}); | |
$("#toolbarButton").off("click"); | |
$("#toolbarButton").hover( | |
function() { | |
if($('#toolTip').length === 0){ | |
$('.v-application--wrap').after(toolTip); | |
} | |
var leftOffset=$('#toolbarButton').offset().left+24-55; | |
var topOffset=$('#toolbarButton').offset().top+46; | |
$('#toolTip').css('left',leftOffset+"px").css('top',topOffset+"px"); | |
$('#toolTip').fadeIn(); | |
}, function() { | |
$('#toolTip').fadeOut(); | |
} | |
); | |
var type; | |
$('#toolbarButton').on('click', function() { | |
var idArray = []; | |
var id = ""; | |
var $borderedCells = $('.item-border').parent().parent().find('.v-image__image').not('.v-image__image--preload'); | |
if( $borderedCells.length !== 1){ | |
$borderedCells.each(function(){ | |
var bookID = $(this).css('background-image').split('/thumbnail')[0].split('/').pop(); | |
var linkType = $(this).css('background-image').split('/thumbnail')[0].split('/'+bookID)[0].split('/').pop(); | |
type = linkType+"_selection"; | |
if ((idArray.indexOf(bookID) === -1)&&(bookID !== "none")){ | |
idArray.push(bookID); | |
} | |
}); | |
if (idArray.length === 0) { | |
return; | |
} | |
if(window.location.href.indexOf("/readlists/") > -1){ | |
type = "readlists_books_selection"; | |
id = window.location.href.split('/readlists/').pop()+";"; | |
} | |
idArray.forEach(function(item) { | |
id += item+";"; | |
}); | |
}else{ | |
id = $borderedCells.css('background-image').split('/thumbnail')[0].split('/').pop(); | |
if(window.location.href.indexOf("/readlists/") > -1){ | |
type = "readlists_books_selection"; | |
var listID = window.location.href.split('/readlists/').pop()+";"; | |
id = listID+id; | |
}else{ | |
type = $borderedCells.css('background-image').split('/thumbnail')[0].split('/'+id)[0].split('/').pop(); | |
} | |
} | |
$("#logContainer").remove(); | |
var ws = new WebSocket(websocket+type+"&id="+id); | |
ws.onopen = function() { | |
overlay.prependTo('.container:first'); | |
$('#toolbarButton').blur(); | |
$("#counter").hide(); | |
$("#counterText").empty(); | |
themeButton(); | |
if(type.includes("_selection")){ | |
$('#thumbnail').css('background-image', 'url('+location.protocol+'//'+location.host+'/api/v1/'+type.split("_")[0]+'/'+id.split(';')[0]+'/thumbnail)'); | |
}else{ | |
$('#thumbnail').css('background-image', 'url('+location.protocol+'//'+location.host+'/api/v1/'+type+'/'+id+'/thumbnail)'); | |
} | |
$('#progressbar').progressbar({value:0}); | |
$('.ui-progressbar-value').css('height', '100%').css('background','var(--v-secondary-base)'); | |
}; | |
ws.onclose = function() { | |
setTimeout(function(){ | |
$('#log').empty(); | |
$('#logContainer').remove(); | |
}, 5000); | |
}; | |
ws.onmessage = function(event) { | |
if (event.data.startsWith("BOOKID:")){ | |
$('#thumbnail').css('background-image', 'url('+location.protocol+'//'+location.host+'/api/v1/books/'+event.data.split("BOOKID:")[1]+'/thumbnail)'); | |
}else if (event.data.startsWith("PROGRESS:")){ | |
$('#progressbar').progressbar({value:parseFloat(event.data.split("PROGRESS:")[1])}); | |
}else if (event.data.startsWith("COUNTER:")){ | |
$('#counter').show(); | |
$('#counter > span').text(event.data.split("COUNTER:")[1]); | |
}else if (event.data.startsWith("FREESPACE:")){ | |
$('.iosstats').show(); | |
$('#freespace').text(event.data.split("FREESPACE:")[1]); | |
}else if (event.data.startsWith("TOTALSPACE:")){ | |
$('.iosstats').show(); | |
$('#capacity').text(event.data.split("TOTALSPACE:")[1]); | |
}else{ | |
log(event.data); | |
} | |
}; | |
}); | |
} | |
} | |
waitForKeyElements (".sticky-bar .mdi-close", addToolbarButton); | |
function themeButton () { | |
$(".tmelement").removeClass('theme--dark theme--light'); | |
var themeToggle = $('label:contains("Theme")')[0].htmlFor; | |
if ($('#'+themeToggle).parent().parent().find('input')[1].value === "theme.dark"){ | |
$(".tmelement").addClass('theme--dark'); | |
} else if ($('#'+themeToggle).parent().parent().find('input')[1].value === "theme.light"){ | |
$(".tmelement").addClass('theme--light'); | |
} | |
} | |
var observer = new MutationObserver(function(mutations) { | |
mutations.forEach(function() { | |
themeButton(); | |
}); | |
}); | |
function log(msg) { | |
if ((msg.endsWith("...")) || (msg.endsWith(": "))) { | |
document.getElementById('log').textContent += msg; | |
}else{ | |
document.getElementById('log').textContent += msg + '\n'; | |
} | |
$('#log').scrollTop($('#log')[0].scrollHeight); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
KOMGA_URL="http://192.168.1.100:8080" | |
KOMGA_USER="why.is.this@anemail.com" | |
KOMGA_PASS="password" | |
IPAD_IP="192.168.1.10" | |
SSH_PASS="password" | |
FILENAME_ARRAY=() | |
PROGRESS=0 | |
TOTALSIZE=0 | |
FILE_CHANGES=false | |
SSH_TEST=$(sshpass -p $SSH_PASS ssh -o ConnectTimeout=3 root@$IPAD_IP 'for p in $(find /var/mobile/Containers/Data -type f -name *plist); do if grep -qi chunky $p 2>/dev/null; then echo $p; fi; done' 2>&1) | |
if [[ $SSH_TEST == *refused* || $SSH_TEST == *timed* || $SSH_TEST == *Unable* ]]; then | |
echo "No SSH server found, exiting" | |
exit 1 | |
else | |
CHUNKY_PATH=`echo $SSH_TEST | cut -d '.' -f1` | |
if [ -z "$CHUNKY_PATH" ]; then | |
echo "Chunky location not found" | |
exit 1 | |
fi | |
fi | |
DF=($(sshpass -p $SSH_PASS ssh root@$IPAD_IP "df -k /dev/disk0s1s2 | tail -1" 2>&1)) | |
TOTAL_CAPACITY=${DF[1]} | |
TOTAL_CAPACITY=`bc <<< 'scale=2; '$TOTAL_CAPACITY'/1024'` | |
if [ `bc <<< $TOTAL_CAPACITY' < 1024'` == 1 ]; then | |
TOTAL_CAPACITY_DISPLAY=$TOTAL_CAPACITY" MB" | |
else | |
TOTAL_CAPACITY_DISPLAY=`bc <<< 'scale=2; '$TOTAL_CAPACITY'/1024'` | |
TOTAL_CAPACITY_DISPLAY=$TOTAL_CAPACITY_DISPLAY" GB" | |
fi | |
echo "TOTALSPACE:Capacity: "$TOTAL_CAPACITY_DISPLAY | |
FREE_SPACE=${DF[3]} | |
FREE_SPACE=`bc <<< 'scale=2; '$FREE_SPACE'/1024'` | |
if [ `bc <<< $FREE_SPACE' < 1024'` == 1 ]; then | |
FREE_SPACE_DISPLAY=$FREE_SPACE" MB" | |
else | |
FREE_SPACE_DISPLAY=`bc <<< 'scale=2; '$FREE_SPACE'/1024'` | |
FREE_SPACE_DISPLAY=$FREE_SPACE_DISPLAY" GB" | |
fi | |
echo "FREESPACE:Available: "$FREE_SPACE_DISPLAY | |
if [ $2 == "readlists" ]; then | |
LIST_JSON=`curl -X 'GET' \ | |
$KOMGA_URL'/api/v1/readlists/'$1 \ | |
-H 'accept: application/json' \ | |
-u $KOMGA_USER:$KOMGA_PASS -s` | |
echo "Reading list: " | |
elif [ $2 == "series" ]; then | |
LIST_JSON=`curl -X 'GET' \ | |
$KOMGA_URL'/api/v1/series/'$1 \ | |
-H 'accept: application/json' \ | |
-u $KOMGA_USER:$KOMGA_PASS -s` | |
echo "Series: " | |
elif [ $2 == "books" ]; then | |
LIST_JSON=`curl -X 'GET' \ | |
$KOMGA_URL'/api/v1/books/'$1 \ | |
-H 'accept: application/json' \ | |
-u $KOMGA_USER:$KOMGA_PASS -s` | |
echo "Selected book: " | |
elif [ $2 == "books_selection" ]||[ $2 == "readlists_books_selection" ]||[ $2 == "series_selection" ]||[ $2 == "readlists_selection" ]; then | |
set -f | |
if [ $2 == "series_selection" ]; then | |
SERIES_IDS=(${1//;/ }) | |
SERIESLIST_LENGTH=${#SERIES_IDS[@]} | |
i=0 | |
echo "Loading series:" | |
while [ $i -lt $SERIESLIST_LENGTH ]; | |
do | |
LIST_JSON=`curl -X 'GET' \ | |
$KOMGA_URL'/api/v1/series/'${SERIES_IDS[i]} \ | |
-H 'accept: application/json' \ | |
-u $KOMGA_USER:$KOMGA_PASS -s` | |
SERIES_LIST_JSON=`curl -X 'GET' \ | |
$KOMGA_URL'/api/v1/series/'${SERIES_IDS[i]}'/books?unpaged=true' \ | |
-H 'accept: application/json' \ | |
-u $KOMGA_USER:$KOMGA_PASS -s` | |
LIST_NAME=`echo $LIST_JSON | jq .name | tr -d '"'` | |
echo '"'$LIST_NAME'"...' | |
BOOKLIST_LENGTH=`jq '.content | length' <<< $SERIES_LIST_JSON` | |
x=0 | |
while [ $x -lt $BOOKLIST_LENGTH ]; | |
do | |
FILENAME=`basename "$(echo $SERIES_LIST_JSON | jq '.content['$x'].url')" .cbz | cut -d'"' -f 1 | tr ' ' '_'` | |
BOOK_ID=`echo $SERIES_LIST_JSON | jq -r '.content['$x'].id'` | |
FILESIZE=`echo $SERIES_LIST_JSON | jq -r '.content['$x'].sizeBytes'` | |
TOTALSIZE=`bc <<< $TOTALSIZE'+'$FILESIZE` | |
BOOK_IDS+=("$BOOK_ID") | |
FILENAME_ARRAY+=("$FILENAME") | |
let x++ | |
done | |
echo "Done" | |
let i++ | |
done | |
elif [ $2 == "readlists_selection" ]; then | |
LIST_IDS=(${1//;/ }) | |
BOOK_IDS=() | |
LIST_NAMES_ARRAY=() | |
else | |
BOOK_IDS=(${1//;/ }) | |
fi | |
if [ $2 == "readlists_selection" ]; then | |
LIST_COUNT=${#LIST_IDS[@]} | |
i=0 | |
echo "Loading reading lists:" | |
while [ $i -lt $LIST_COUNT ]; | |
do | |
LIST_JSON=`curl -X 'GET' \ | |
$KOMGA_URL'/api/v1/readlists/'${LIST_IDS[i]} \ | |
-H 'accept: application/json' \ | |
-u $KOMGA_USER:$KOMGA_PASS -s` | |
READLIST_JSON=`curl -X 'GET' \ | |
$KOMGA_URL'/api/v1/readlists/'${LIST_IDS[i]}'/books?unpaged=true' \ | |
-H 'accept: application/json' \ | |
-u $KOMGA_USER:$KOMGA_PASS -s` | |
LIST_NAME=`echo $LIST_JSON | jq .name | tr -d '"'` | |
echo '"'$LIST_NAME'"...' | |
BOOKLIST_LENGTH=`jq '.content | length' <<< $READLIST_JSON` | |
x=0 | |
while [ $x -lt $BOOKLIST_LENGTH ]; | |
do | |
FILENAME=`basename "$(echo $READLIST_JSON | jq '.content['$x'].url')" .cbz | cut -d'"' -f 1 | tr ' ' '_'` | |
BOOK_ID=`echo $READLIST_JSON | jq -r '.content['$x'].id'` | |
FILESIZE=`echo $READLIST_JSON | jq -r '.content['$x'].sizeBytes'` | |
TOTALSIZE=`bc <<< $TOTALSIZE'+'$FILESIZE` | |
BOOK_IDS+=("$BOOK_ID") | |
LIST_NUM=`printf "%03d\n" $(($x+1))` | |
FILENAME=${LIST_NUM}_-_${FILENAME} | |
FILENAME_ARRAY+=("$FILENAME") | |
LIST_NAMES_ARRAY+=("$LIST_NAME") | |
let x++ | |
done | |
echo "Done" | |
let i++ | |
done | |
fi | |
if [ $2 == "readlists_books_selection" ]; then | |
LIST_ID=${BOOK_IDS[0]} | |
unset 'BOOK_IDS[0]' | |
BOOK_IDS=(${BOOK_IDS[@]}) | |
LIST_JSON=`curl -X 'GET' \ | |
$KOMGA_URL'/api/v1/readlists/'$LIST_ID \ | |
-H 'accept: application/json' \ | |
-u $KOMGA_USER:$KOMGA_PASS -s` | |
LIST_BOOK_IDS=( $(jq -cr .bookIds[] <<< $LIST_JSON) ) | |
LIST_NAME=`echo $LIST_JSON | jq .name | tr -d '"'` | |
echo 'Reading list: "'$LIST_NAME'"' | |
fi | |
BOOKLIST_LENGTH=${#BOOK_IDS[@]} | |
echo "COUNTER:"$BOOKLIST_LENGTH | |
if [ $BOOKLIST_LENGTH == "1" ]; then | |
echo 'Selection has '$BOOKLIST_LENGTH' book' | |
else | |
echo 'Selection has '$BOOKLIST_LENGTH' books' | |
fi | |
if [ $2 == "readlists_selection" ]||[ $2 == "readlists_books_selection" ]; then | |
PROGRESS_AMOUNT=`bc <<< 'scale=2; 90/'$BOOKLIST_LENGTH` | |
else | |
PROGRESS_AMOUNT=`bc <<< 'scale=2; 100/'$BOOKLIST_LENGTH` | |
fi | |
if [ $2 != "series_selection" ]&&[ $2 != "readlists_selection" ]; then | |
i=0 | |
while [ $i -lt $BOOKLIST_LENGTH ]; | |
do | |
if [ $2 == "readlists_books_selection" ]; then | |
for x in "${!LIST_BOOK_IDS[@]}"; | |
do | |
if [[ "${LIST_BOOK_IDS[$x]}" = "${BOOK_IDS[i]}" ]]; | |
then | |
LIST_NUM=`printf "%03d\n" $(($x+1))` | |
fi | |
done | |
fi | |
FILE_LIST_JSON=`curl -X 'GET' \ | |
$KOMGA_URL'/api/v1/books/'${BOOK_IDS[i]} \ | |
-H 'accept: application/json' \ | |
-u $KOMGA_USER:$KOMGA_PASS -s` | |
STATUS=`echo $FILE_LIST_JSON | jq .status` | |
FILESIZE=`echo $FILE_LIST_JSON | jq -r '.sizeBytes'` | |
TOTALSIZE=`bc <<< $TOTALSIZE'+'$FILESIZE` | |
if [ $STATUS == "404" ]; then | |
echo "Unknown Komga file ID" | |
exit 1 | |
fi | |
FILENAME=`basename "$(echo $FILE_LIST_JSON | jq .url)" .cbz | cut -d'"' -f 1 | tr ' ' '_'` | |
if [ $2 == "readlists_books_selection" ]; then | |
FILENAME=$LIST_NUM"_-_"$FILENAME | |
fi | |
FILENAME_ARRAY+=("$FILENAME") | |
let i++ | |
done | |
fi | |
TOTALSIZE=`bc <<< 'scale=2; '$TOTALSIZE'/1024/1024'` | |
if [ `bc <<< $TOTALSIZE' < 1024'` == 1 ]; then | |
TOTALSIZE_DISPLAY=$TOTALSIZE" MB" | |
else | |
TOTALSIZE_DISPLAY=`bc <<< 'scale=2; '$TOTALSIZE'/1024'` | |
TOTALSIZE_DISPLAY=$TOTALSIZE_DISPLAY" GB" | |
fi | |
echo "Size: "$TOTALSIZE_DISPLAY | |
fi | |
if [ $2 != "books_selection" ]&&[ $2 != "series_selection" ]&&[ $2 != "readlists_selection" ]&&[ $2 != "readlists_books_selection" ]; then | |
STATUS=`jq .status <<< $LIST_JSON` | |
if [ $STATUS == "404" ]; then | |
echo "Unknown Komga "$2" ID" | |
exit 1 | |
fi | |
LIST_NAME=`echo $LIST_JSON | jq .name | tr -d '"'` | |
echo '"'$LIST_NAME'"' | |
fi | |
if [ $2 == "readlists" ]||[ $2 == "series" ]; then | |
BOOK_IDS=() | |
if [ $2 == "readlists" ]; then | |
BOOKLIST_JSON=`curl -X 'GET' \ | |
$KOMGA_URL'/api/v1/readlists/'$1'/books?unpaged=true' \ | |
-H 'accept: application/json' \ | |
-u $KOMGA_USER:$KOMGA_PASS -s` | |
elif [ $2 == "series" ]; then | |
BOOKLIST_JSON=`curl -X 'GET' \ | |
$KOMGA_URL'/api/v1/series/'$1'/books?unpaged=true' \ | |
-H 'accept: application/json' \ | |
-u $KOMGA_USER:$KOMGA_PASS -s` | |
fi | |
BOOKLIST_LENGTH=`jq '.content | length' <<< $BOOKLIST_JSON` | |
if [ $2 == "readlists" ]; then | |
PROGRESS_AMOUNT=`bc <<< 'scale=2; 90/'$BOOKLIST_LENGTH` | |
elif [ $2 == "series" ]; then | |
PROGRESS_AMOUNT=`bc <<< 'scale=2; 100/'$BOOKLIST_LENGTH` | |
fi | |
echo "COUNTER:"$BOOKLIST_LENGTH | |
if [ $2 == "readlists" ]; then | |
TYPE="Reading list" | |
elif [ $2 == "series" ]; then | |
TYPE="Series" | |
fi | |
if [ $BOOKLIST_LENGTH == "1" ]; then | |
echo $TYPE' has '$BOOKLIST_LENGTH' book' | |
else | |
echo $TYPE' has '$BOOKLIST_LENGTH' books' | |
fi | |
echo "Processing book list..." | |
i=0 | |
while [ $i -lt $BOOKLIST_LENGTH ]; | |
do | |
FILENAME=`basename "$(echo $BOOKLIST_JSON | jq '.content['$i'].url')" .cbz | cut -d'"' -f 1 | tr ' ' '_'` | |
BOOK_ID=`echo $BOOKLIST_JSON | jq -r '.content['$i'].id'` | |
FILESIZE=`echo $BOOKLIST_JSON | jq -r '.content['$i'].sizeBytes'` | |
TOTALSIZE=`bc <<< $TOTALSIZE'+'$FILESIZE` | |
BOOK_IDS+=("$BOOK_ID") | |
if [ $2 == "readlists" ]; then | |
LIST_NUM=`printf "%03d\n" $(($i+1))` | |
FILENAME=${LIST_NUM}_-_${FILENAME} | |
fi | |
FILENAME_ARRAY+=("$FILENAME") | |
let i++ | |
done | |
echo "Done" | |
TOTALSIZE=`bc <<< 'scale=2; '$TOTALSIZE'/1024/1024'` | |
if [ `bc <<< $TOTALSIZE' < 1024'` == 1 ]; then | |
TOTALSIZE_DISPLAY=$TOTALSIZE" MB" | |
else | |
TOTALSIZE_DISPLAY=`bc <<< 'scale=2; '$TOTALSIZE'/1024'` | |
TOTALSIZE_DISPLAY=$TOTALSIZE_DISPLAY" GB" | |
fi | |
echo "Size: "$TOTALSIZE_DISPLAY | |
elif [ $2 == "books" ]; then | |
FILESIZE=`echo $LIST_JSON | jq -r '.sizeBytes'` | |
FILESIZE=`bc <<< 'scale=2; '$FILESIZE'/1024/1024'` | |
echo "Size: "$FILESIZE" MB" | |
LIST_FILENAME=`basename "$(echo $LIST_JSON | jq .url)" .cbz | cut -d'"' -f 1 | tr ' ' '_'` | |
BOOK_IDS=("$1") | |
fi | |
if [ `bc <<< $TOTALSIZE' > '$FREE_SPACE` == 1 ]; then | |
echo | |
echo "This is larger than the available free space on the iPad" | |
exit 1 | |
fi | |
if [ $2 == "readlists" ]||[ $2 == "readlists_selection" ]||[ $2 == "readlists_books_selection" ]; then | |
echo | |
echo "Activating Chunky" | |
sshpass -p $SSH_PASS ssh root@$IPAD_IP 'open com.mike-ferenduros.Chunky-Comic-Reader' | |
echo "Turning off Auto-Lock" | |
sshpass -p $SSH_PASS ssh root@$IPAD_IP 'activator send switch-off.com.a3tweaks.switch.autolock' | |
PROGRESS=`bc <<< 'scale=2; '$PROGRESS'+2'` | |
echo "PROGRESS:"$PROGRESS | |
fi | |
echo | |
echo "Transferring files" | |
for i in ${!BOOK_IDS[@]}; do | |
if [ $2 != "books" ]; then | |
LIST_FILENAME=${FILENAME_ARRAY[$i]} | |
fi | |
echo "BOOKID:"${BOOK_IDS[$i]} | |
LIST_FILENAME=`echo $LIST_FILENAME | tr '_' ' '` | |
echo $(($i+1))". \""$LIST_FILENAME"\"..." | |
if ! (sshpass -p $SSH_PASS ssh root@$IPAD_IP stat \"$CHUNKY_PATH/Documents/$LIST_FILENAME\" \> /dev/null 2\>\&1) ; then | |
sshpass -p $SSH_PASS ssh root@$IPAD_IP 'curl -X "GET" '$KOMGA_URL'"/api/v1/books/"'${BOOK_IDS[$i]}'"/file" -H "accept: application/octet-stream" -u '$KOMGA_USER:$KOMGA_PASS' --output "'$CHUNKY_PATH/Documents/$LIST_FILENAME'"' | |
echo "Done" | |
DF=($(sshpass -p $SSH_PASS ssh root@$IPAD_IP "df -k /dev/disk0s1s2 | tail -1" 2>&1)) | |
FREE_SPACE=${DF[3]} | |
FREE_SPACE=`bc <<< 'scale=2; '$FREE_SPACE'/1024'` | |
if [ `bc <<< $FREE_SPACE' < 1024'` == 1 ]; then | |
FREE_SPACE_DISPLAY=$FREE_SPACE" MB" | |
else | |
FREE_SPACE_DISPLAY=`bc <<< 'scale=2; '$FREE_SPACE'/1024'` | |
FREE_SPACE_DISPLAY=$FREE_SPACE_DISPLAY" GB" | |
fi | |
echo "FREESPACE:Available: "$FREE_SPACE_DISPLAY | |
FILE_CHANGES=true | |
else | |
echo "Skipped (Already exists)" | |
fi | |
PROGRESS=`bc <<< 'scale=2; '$PROGRESS'+'$PROGRESS_AMOUNT` | |
echo "PROGRESS:"$PROGRESS | |
done | |
if [ $2 == "readlists" ]||[ $2 == "readlists_selection" ]||[ $2 == "readlists_books_selection" ]; then | |
if [ $FILE_CHANGES == true ]; then | |
echo | |
echo "Waiting for Chunky to finish loading files" | |
sleep 10 | |
echo "Turning Auto-Lock back on" | |
sshpass -p $SSH_PASS ssh root@$IPAD_IP 'activator send switch-on.com.a3tweaks.switch.autolock' | |
echo "Killing Chunky" | |
sshpass -p $SSH_PASS ssh root@$IPAD_IP 'killall "Chunky Comic Reader"' | |
echo "Editing Database" | |
sshpass -p $SSH_PASS scp root@$IPAD_IP:$CHUNKY_PATH/Library/PrivateDB/db-011.sqlite3 . 2>&1 | |
for i in ${!FILENAME_ARRAY[@]}; do | |
if [ $2 == "readlists_selection" ]; then | |
LIST_NAME=`echo ${LIST_NAMES_ARRAY[$i]} | tr '_' ' '` | |
fi | |
LIST_NAME_SIMPLE=`echo $LIST_NAME | tr -dc '[:alnum:]\n\r ' | tr '[:upper:]' '[:lower:]'` | |
filename=`echo ${FILENAME_ARRAY[$i]} | tr '_' ' '` | |
sqlite3 db-011.sqlite3 <<END_SQL | |
update Book set manualGroupName='$LIST_NAME', groupName='$LIST_NAME_SIMPLE' where filename='$filename'; | |
END_SQL | |
done | |
sshpass -p $SSH_PASS scp -r db-011.sqlite3 root@$IPAD_IP:$CHUNKY_PATH/Library/PrivateDB/ 2>&1 | |
echo "Relaunching Chunky" | |
sshpass -p $SSH_PASS ssh root@$IPAD_IP 'open com.mike-ferenduros.Chunky-Comic-Reader' | |
rm db-011.sqlite3 | |
else | |
echo | |
echo "No database changes necessary" | |
echo "Turning Auto-Lock back on" | |
sshpass -p $SSH_PASS ssh root@$IPAD_IP 'activator send switch-on.com.a3tweaks.switch.autolock' | |
fi | |
fi | |
echo | |
echo "PROGRESS:100" | |
echo "Done!" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
OIFS=$IFS | |
IFS='&' read -r -a query <<< "$QUERY_STRING" | |
ID=`printf '%s\0' "${query[@]}" | grep -F -z 'id' | rev | cut -d"=" -f1 | rev` | |
TYPE=`printf '%s\0' "${query[@]}" | grep -F -z 'type' | rev | cut -d"=" -f1 | rev` | |
./newDownloader.sh $ID $TYPE | |
IFS=$OIFS |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment