lelinhtinh / jEpub

Simple EPUB builder library, works in modern browsers.
https://lelinhtinh.github.io/jEpub/
ISC License
46 stars 19 forks source link

Usage of jEpub in UserLibrary (userscript) #3

Closed nntoan closed 5 years ago

nntoan commented 5 years ago

Hello,

In my case, I require jEpub in an UserLibrary then I require that UserLibrary into a normal UserScript.

E.g:

// ==UserScript==
// @name         TangThuVien downloader
// @match        http://truyen.tangthuvien.vn/doc-truyen/*
// @match        https://truyen.tangthuvien.vn/doc-truyen/*
// @require      https://greasyfork.org/scripts/383027-mb-downloader-library/code/MB%20Downloader%20Library.js?version=698206
// @connect      self
// @run-at       document-idle
// @noframes
// ==/UserScript==

But it is showing this

Screenshot 2019-05-15 12 42 49

It will work if I changed from UserLibrary to UserScript. Do you know why this happening?

P/s: Thank you so much for creating TruyenCV_downloader, I steal lots of code from you :) 👍 👍 💯 💯

lelinhtinh commented 5 years ago

UserLibrary không phải là định dạng Metadata Block chuẩn, nó bắt buộc phải là UserScript. Mình cũng thấy một số thư viện trên Greasyfork dùng UserLibrary, có lẽ chỉ để cho đẹp, cho hợp mục đích sử dụng. Vì thế khi nhúng vào @require thì nó chỉ như tệp JavaScript thông thường, phần comment không có giá trị, các GM API cũng không hoạt động bên trong thư viện.

nntoan commented 5 years ago

Vậy theo bạn mình nên làm gì trong trường hợp này ? Có nên chuyển nó sang một repository riêng và đưa lên npmjs hay để nó thành một userscript bình thường?

lelinhtinh commented 5 years ago

Bạn chỉ cần thêm jEpub vào phần @require của TangThuVien downloader, và không dùng GM API trong thư viện là được.

// @require      https://unpkg.com/jepub@1.2.5/dist/jepub.min.js
// @require      https://greasyfork.org/scripts/383027-mb-downloader-library/code/MB%20Downloader%20Library.js?version=698206

... tất nhiên là bao gồm cả jQuery và FileSaver nữa (nếu có sử dụng).

nntoan commented 5 years ago

À, tại vì mình muốn sử dụng jEpub/FileSaver trong thằng userlibrary để không cần phải require nó trong các userscript extend từ library, không biết UserScript có hỗ trợ việc chain require như thế không hả bạn?

lelinhtinh commented 5 years ago

Không làm vậy được, khi dùng ở @require thì nó chỉ là tệp JavaScript thông thường thôi, không có thêm chức năng nào khác, bạn có dùng Metadata Block trong đó cũng không có ý nghĩa.

nntoan commented 5 years ago

Thank bạn rất nhiều giờ mình mới biết :D

Mình đang viết lại nó thành một repository mới để đưa lên npmjs, mình hơi thắc mắc chút là nếu mình để dependency trong package.json thì khi lên unpkg, nó sẽ tự thêm các dependecies vào file js của minnh đúng ko bạn?

Screenshot 2019-05-15 14 43 09

Screenshot 2019-05-15 14 43 03

lelinhtinh commented 5 years ago

Không, trong jEpub mình dùng Webpack để làm điều đó. Nhưng từ v2.0.0 mình đã bỏ nén chung với các thư việc phụ thuộc khác để thuận tiện cho việc nâng cấp riêng lẻ.

nntoan commented 5 years ago

@lelinhtinh Bạn có biết vì sao callback trong then() của hàm generate().then(callback) không chạy được không nhỉ?

Ví dụ

Screenshot 2019-05-16 18 18 44

Nó chỉ hiện Promise pending rồi đứng im luôn. Mọi code bên trong then() đều unreachable :(

Screenshot 2019-05-16 18 22 30

Code: https://github.com/nntoan/mbDownloader

lelinhtinh commented 5 years ago

Lỗi đó có vẻ như là jepub vẫn đang chạy sau khi gọi generate(). Bạn thử log thứ tự từng bước jepub hoạt động xem có gì sai không? Gửi mình code bạn dùng tải truyện mà xuất hiện lỗi đó xem.

Trong mbDownloader, cách bạn thêm cover vào ebook không đúng, phải là ảnh dạng binary array buffers. Hàm generateUUID() là không cần thiết vì jEpub có sẵn rồi, bạn bỏ qua jepub.uuid() thì nó sẽ tự tạo UUID.

Ngoài ra bạn cũng nên cập nhật jEpub lên v2, có lỗi sẽ dễ hỗ trợ hơn bản cũ, cũng không nhiều thay đổi:

Mình vừa nâng cấp TruyenCV downloader, bạn có thể tham khảo.

nntoan commented 5 years ago

Có vẻ như đang có bug gì đó ở đoạn này:

Screenshot 2019-05-17 14 21 30

Lenght của generate() đang là 0 thay vì 1 (giống như hàm cover() bên trên).

Hơn nữa kiểu của generate() cũng không phải là function ???

P/s Ừ mình chưa viết hàm fetch cho image cover, nên vẫn để đó thôi.

nntoan commented 5 years ago

@lelinhtinh Sau khi upgrade lên 2 chấm jEpub thì nó lại chạy không hiểu vì sao :D

https://github.com/nntoan/UserScripts/tree/master/TTV_downloader

lelinhtinh commented 5 years ago

Có bản 2.1.1 rồi đó bạn, sửa lỗi MIME khi dùng dữ liệu ảnh ArrayBuffer.

Trong jEpub có 2 phương thức dùng ảnh là .cover().image() để thêm ảnh vào nội dung chương truyện. Cả 2 đều nhận dữ liệu ảnh là Blob hoặc ArrayBuffer. Lý do mình không dùng link ảnh là vì hạn chế same-origin policy, nó không cho phép tải resource khác nguồn (bao gồm hình ảnh). Các trang web thường chứa resource trên CDN để giảm tải, nên sẽ khác nguồn, vì thế JavaScript không tải được (trừ khi bật CORS). Trong mbDownloader của bạn mình thấy có phương thức fetchCoverImage(), nhiều khả năng nó sẽ không tải được cover vì lý do trên. Bạn nên dùng GM.xmlHttpRequest hoặc GM_xmlhttpRequest (API cũ) để tải ảnh về dạng dữ liệu ArrayBuffer (còn Blob sẽ có lỗi trên Firefox, mình chưa tìm ra lý do). Ví dụ cách mình dùng trong TruyenCV downloader. GM API không làm việc trong thư viện, nên phần lấy dữ liệu ảnh này bạn phải đặt trong TTV_downloader, chứ không phải mbDownloader.

Trong trường hợp vẫn muốn sử dụng link ảnh, bạn có thể dùng proxy như CORS Anywhere. Có thể dùng server thử nghiệm của họ (không ổn định), bằng cách thêm https://cors-anywhere.herokuapp.com/ vào trước link ảnh:

fetch('https://cors-anywhere.herokuapp.com/https://www.nae.vn/ttv/ttv/public/images/story/ecbd8cce7d61e08f0c64c7f4cbc1fbb7bb34735c7437147f2a1d0ca02801af69.jpg').then(function(response) {
    if (response.ok) return response.arrayBuffer();
}).then(function(response) {
    console.log(response)
}).catch(function(error) {
    console.error(error);
});
nntoan commented 5 years ago

@lelinhtinh Chuẩn rồi, fetch() nó vẫn cho lấy opaq response nhưng chỉ cho dùng trong worker hoặc localStorage nếu server-side không allow CORS.

Lần đầu mình biết vụ https://cors-anywhere.herokuapp.com/ đó. Thanks bác nhiều.

Đây cùng là một trong số lý do mình muốn move hết code của bác sang 1 lib riêng thành jQuery widget vì việc extend sẽ dễ hơn rất là nhiều mà lại không bị copy code đi khắp nơi, write once runs everywhere :)

Bác có rảnh thì contribute cùng mình vì dù sao bác cũng là original author mà :D

Mà mình cũng mới phát hiện hình như có 1 bug liên quan đến performance của jEpub lúc nó generate, có vẻ như chậm hơn cả bản trước đó.

Nó nén rất là lâu, nếu nó đứng quá 15s mà chưa download được epub là mình buộc phải bật DevTools lên thì cái download popup nó mới hiện ra !?! hơi khó hiểu đoạn này.

P/s: nếu bác muốn reproduce thì tìm bộ nào thật nhiều chương vì ae mình lúc test thì thường hay ngắt sớm để test đoạn generate luôn. vd bộ này: https://truyen.tangthuvien.vn/doc-truyen/sieu-cap-than-co-nhan-超级神基因 (3k chương...) hoặc bộ nào treen1k chương cũng dính: https://truyencv.com/vong-linh-phap-su-mat-the-hanh/

lelinhtinh commented 5 years ago

Trong v2 mình nén chapter ngay khi tải, thay vì nén đồng loạt khi kết thúc như v1. Ban đầu kỳ vọng là nó sẽ nhanh hơn, nhưng thực tế đúng là chậm hơn vài giây, cũng không đáng kể nên mình chưa để tâm lắm. Vụ không tự tải xuống có thể là do bị chặn Blob URL, nhất là khi cài extension chặn popup. Mình không rành jQuery UI lắm, lúc trước cũng nhiều lần định viết một script tổng hợp mà còn mớ truyện chưa đọc nên cũng... lười.

nntoan commented 5 years ago

Theo mình nên để lại vụ nén đồng loạt khi kết thúc vì nén từng chapter trong lúc tải sẽ làm cho memory của tab ngày càng lên cao. Nó sẽ ảnh hưởng performance nếu bạn download nhiều truyện cùng lúc.

Nén tất cả 1 lúc vào cuối cùng sẽ chỉ thêm đc căng đét 20MB ram và chủ yếu là nặng CPU bù lại nếu trường hợp bác download nhiều truyện cùng lúc sẽ rất khó gặp trường hợp vài tab đều đang trong tình trạng nén chapter cùng lúc vì số chapter mỗi truyện khác nhau.

Nên thực tế phương thức nén của bản cũ lại tối ưu hơn và nhanh hơn.

Mình đã hoàn thiện tương đối phần xương cho mbDownloader rồi, bác có thể xem tại đây: https://github.com/nntoan/mbDownloader

Các method đều có thể extend theo cách mình đang làm tại TTV Downloader vì jQuery UI nó sẽ hỗ trợ this._super().