Adding queue for download.

This commit is contained in:
Vahagn Khachatryan
2019-02-09 10:59:51 +00:00
parent 5365385bd5
commit 0654ae807a
2 changed files with 269 additions and 127 deletions

View File

@@ -22,30 +22,19 @@
</style>
</head>
<body>
<button id="download-book-button" type="button" class="btn btn-outline-primary">Download Book</button>
<div class="status">
<p id="error-message" class="bg-warning"></p>
<div class="loader" id="loading" style="display:none;">
<p class="bg-success">
<strong>
Loading book info
<span class="loader__dot">.</span>
<span class="loader__dot">.</span>
<span class="loader__dot">.</span>
</strong>
</p>
</div>
<!-- <button id="add-book-button" type="button" class="btn btn-primary">Add Book</button> -->
<button id="download-book-button" type="button" class="btn btn-primary">Download</button>
<div id="book-list" class="container">
<ul id="book-queue" class="list-group">
</ul>
</div>
<div id="book-info" class="container">
<h4 id="book-info-notice"></h4>
<img id="book-cover" src="" class="img-fluid">
<p class="bg-success">
<span><strong>Book Name:</strong></span>
<span id="book-name"></span>
</p>
<img id="book-cover" src="" class="img-fluid">
<p class="bg-success">
<span ><strong>Progress: </strong></span>
</p>
@@ -54,26 +43,16 @@
</div>
<div id="download-section">
<p id="download-warning" style="display: none;" class="bg-warning"></p>
<button id="download-button" type="button" style="display: none;" class="btn btn-primary">Download above chapters as zip package</button>
<p id="book-name"><strong></strong></p>
<div id="status"></div>
<img id="image-result" hidden>
</div>
<link rel="stylesheet" href="3pty/bootstrap.min.css">
<script src="3pty/bluebird.js"></script>
<script src="3pty/jszip.js"></script>
<script src="epub.js"></script>
<script src="sidebar.js"></script>
<script src="3pty/jquery-3.1.1.slim.min.js"></script>
<script src="3pty/tether.min.js"></script>
<script src="3pty/bootstrap.min.js"></script>
<script src="epub.js"></script>
<script src="sidebar.js"></script>
</body>
</html>

View File

@@ -1,48 +1,12 @@
var concurrency = 5
var retry_delay = 15/* seconds */
var book_delay = 300/* seconds */
var download_list = []
function sleep(delay) {
return new Promise((resolve) => setTimeout(resolve, delay*1000));
}
function getCurrentTab() {
console.debug("Querying active tab.");
var queryInfo = {
active: true,
currentWindow: true
};
return browser.tabs.query(queryInfo)
.then(function(tabs) {
if (tabs.length == 1){
let url = tabs[0].url;
console.info(`Active URL: ${url}`);
return url;
} else {
console.error(`Expected 1 active tab, received: ${tabs}`);
throw 'Failed to get active tab.';
}
});
}
function extractBookId(url){
console.debug(`Extracting book id from ${url}`);
// match a url like:
// https://www.safaribooksonline.com/library/view/startup-opportunities-2nd/9781119378181/
// https://www.safaribooksonline.com/library/view/startup-growth-engines/77961SEM00001/
let match = url.match(/\/library\/view\/[^\/]+\/(\w+)\//);
let bookId = match && match[1];
if (bookId) {
console.debug(`Extracted book id: ${bookId}`);
return bookId;
}else{
console.error('Could not extract book id from url, only '
+'domain "www.safaribooksonline.com“ is supported.');
throw 'Failed to extract book id.';
}
}
class Book{
constructor(book_id, page) {
@@ -57,6 +21,25 @@ class Book{
this.page = page
}
addToLocalPlaylist(){
let method = "https://learning.oreilly.com/api/v2/collections/92f0712e-eb58-4c6e-939e-d5c57a7e6d90/add-content/"
let request = {
content: [`/api/v1/book/${this.book_id}/`]
}
return fetch(method, {
method: "post",
body: JSON.stringify(request),
headers: new Headers({
"Accept" : "application/json; version=v2",
"Content-Type": "application/json"
}),
credentials: 'include'
})
.then((res)=>{
console.warn(`Post ${method} - ${res.status} - ${res.statusText}`)
})
}
downloadResource(url, retry=false){
if (retry){
console.warn(`Retry ${url}`)
@@ -212,50 +195,120 @@ class Book{
}
}
/*************************************************************************/
class SidebarPage{
constructor() {
$('#loading').show();
$('#error-message').hide();
$('#book-info').hide();
$("#book-file-list").empty();
$('#book-info').hide()
this.id = 1
}
renderInfo(book){
$("#book-name").text(book.book_info.title);
getUniqueueId(){
let id = `item_${this.id}`
this.id++
return id
}
loading_animatedDot(){
return $('<snap/>')
.addClass('loader__dot')
.text('.')
}
loading_animation(){
return $('<snap/>')
.attr('id', 'dot_animation')
.append(this.loading_animatedDot())
.append(this.loading_animatedDot())
.append(this.loading_animatedDot())
}
remove_loading_animation(){
$('#dot_animation').remove()
}
/****************************************************/
renderBookItemId(book_id){
let id = this.getUniqueueId()
let link = $('<a/>')
.attr('href', `https://learning.oreilly.com/search/?query=${book_id}`)
.attr('id', `a_${id}`)
.text(`${book_id}`)
var book_item =
$("<li></li>")
.addClass("list-group-item")
.attr('id', id)
.append(link)
$("#book-queue").prepend(book_item);
return id
}
renderBookItemNameAndURL(id, name, url){
$('#a_'+id)
.attr('href', url)
.text(name)
}
renderBookItemAnimatedLoading(id){
$('#'+id)
.append(this.loading_animation())
}
renderBookItemSuccess(id){
this.remove_loading_animation()
$('#'+id)
.css( "color", "green" )
.append(' - OK');
}
renderBookItemFail(id, err){
this.remove_loading_animation()
$('#'+id)
.css( "color", "red" )
.append(' - Fail: ')
.append(err)
}
/****************************************************/
renderBookBeginLoading(id){
$('#book-info').hide();
$("#book-file-list").empty();
this.renderBookItemAnimatedLoading(id)
}
renderBookInfo(book, id){
$("#book-cover").attr("src", book.book_info.cover);
let link = $('<a/>')
.attr('href', book.book_info.web_url)
.text(book.book_info.title)
$("#book-name").empty()
.append(link);
this.renderBookItemNameAndURL(id,
book.book_info.title,
book.book_info.web_url)
$('#book-info').show();
}
renderDoneWithBook(){
$('#loading').hide();
renderBookSuccess(id){
this.renderBookItemSuccess(id)
}
renderFailedTheBook(error) {
console.error(`Error: ${error}`);
$('#loading').hide();
$('#error-message').text(`Error: ${error}`);
$('#error-message').show();
// $('#book-info').hide();
renderBookFail(id, err){
this.renderBookItemFail(id, err)
}
renderChapterList(book){
// Add chapters to UI
for (let chapter_idx in book.chapter_list) {
let chapter = book.chapter_list[chapter_idx];
var chapter_dom = $("<li></li>")
.addClass("list-group-item")
.html(chapter.title)
.attr("chapterIndex", chapter_idx);
$("#book-chapter-list").append(chapter_dom);
}
$('#loading').hide();
}
/****************************************************/
renderProgress(txt){
let id = `item_${this.id}`
this.id++
let id = this.getUniqueueId()
// Add chapters to UI
var progress_dom = $("<li></li>")
.addClass("list-group-item")
@@ -278,7 +331,9 @@ class SidebarPage{
.attr('title',reason.message);
}
}
var page = new SidebarPage()
/*********************************************************/
function fillMetadata(epub, book)
{
@@ -390,20 +445,13 @@ function createEpub(book, epub){
}
}
/*********************************************************************/
function onDownloadBookClicked(){
console.info("Begin book download.");
page = new SidebarPage()
getCurrentTab()
.then(extractBookId)
.then((book_id) => {
epub = new EpubWriter();
book = new Book(book_id, page);
function downloadBook(book_id, item_id){
let epub = new EpubWriter();
let book = new Book(book_id, page);
return book.downloadBookInfo()
.then(() => { page.renderInfo(book); })
// .then(() => { return book.downloadChapterList(); })
// .then(() => { return page.renderChapterList(book); })
.then(() => { page.renderBookInfo(book, item_id); })
.then(() => { return book.downloadMetaContent(); })
.then(() => { return book.downloadContent(); })
.then(() => { return createEpubStructure(book, epub); })
@@ -419,15 +467,132 @@ function onDownloadBookClicked(){
let url = window.URL.createObjectURL(file)
return browser.downloads.download({ "filename" : filename, url : url})
})
.then(()=>{
// Add to playlist "local" to indicate that this book
// is already downloaded.
return book.addToLocalPlaylist()
})
}
/*********************************************************************/
var progress = false
function downloadNextBook(){
progress = true
let download = download_list.pop()
item_id = download.page_id
book_id = download.book_id
page.renderBookBeginLoading(item_id)
downloadBook(book_id, item_id)
.then(() =>{
page.renderDoneWithBook();
page.renderBookSuccess(item_id);
})
.catch((error)=>{
page.renderFailedTheBook(error);
page.renderBookFail(item_id, error);
})
.then(()=>{
if (download_list.length){
return sleep(book_delay)
.then(()=>{
return downloadNextBook()
})
}
else{
progress = false
}
});
}
/*********************************************************************/
function getCurrentTabUrl() {
console.debug("Querying active tab.");
var queryInfo = {
active: true,
currentWindow: true
};
return browser.tabs.query(queryInfo)
.then(function(tabs) {
if (tabs.length == 1){
let url = tabs[0].url;
console.info(`Active URL: ${url}`);
return url;
} else {
console.error(`Expected 1 active tab, received: ${tabs}`);
throw 'Failed to get active tab.';
}
});
}
function closeCurrentTab() {
console.debug("Querying active tab.");
var queryInfo = {
active: true,
currentWindow: true
};
return browser.tabs.query(queryInfo)
.then(function(tabs) {
if (tabs.length == 1){
let tabId = tabs[0].id;
console.info(`Closing tab: ${tabId}`);
return browser.tabs.remove(tabId);
} else {
console.error(`Expected 1 active tab, received: ${tabs}`);
throw 'Failed to get active tab.';
}
});
}
function extractBookId(url){
console.debug(`Extracting book id from ${url}`);
// match a url like:
// https://www.safaribooksonline.com/library/view/startup-opportunities-2nd/9781119378181/
// https://www.safaribooksonline.com/library/view/startup-growth-engines/77961SEM00001/
let match = url.match(/\/library\/view\/[^\/]+\/(\w+)\//);
let bookId = match && match[1];
if (bookId) {
console.debug(`Extracted book id: ${bookId}`);
return bookId;
}else{
console.error('Could not extract book id from url, only '
+'domain "www.safaribooksonline.com“ is supported.');
throw 'Failed to extract book id.';
}
}
function onDownloadBookClicked(){
console.info("Begin book download.");
getCurrentTabUrl()
.then((url)=>{
return extractBookId(url)
})
.then((book_id)=>{
closeCurrentTab()
return book_id
})
.then((book_id)=>{
page_id = page.renderBookItemId(book_id)
download_list.push({
book_id : book_id,
page_id : page_id
})
})
.then(()=>{
if (download_list.length && !progress){
downloadNextBook()
}
})
}
document.addEventListener('DOMContentLoaded', function() {
console.log("Start safari book hunter.");
$('#loading').hide();
@@ -438,8 +603,6 @@ document.addEventListener('DOMContentLoaded', function() {
onDownloadBookClicked();
});
$('#deselect-all-button').show()
$('#download-button').show()
$('#download-section').hide();