5 files changed
+143
-92
No files matched your search
@@ -9,6 +9,8 @@ asttokens==2.4.1
|
||||
async-timeout==4.0.3
|
||||
attrs==23.1.0
|
||||
backoff==2.2.1
|
||||
beautifulsoup4==4.12.3
|
||||
bs4==0.0.2
|
||||
click==8.1.7
|
||||
comm==0.2.0
|
||||
debugpy==1.8.0
|
||||
@@ -48,6 +50,7 @@ pyzmq==25.1.2
|
||||
rich==13.7.0
|
||||
six==1.16.0
|
||||
sniffio==1.3.0
|
||||
soupsieve==2.5
|
||||
stack-data==0.6.3
|
||||
starlette==0.32.0.post1
|
||||
tornado==6.4
|
||||
|
||||
@@ -6,6 +6,7 @@ import backoff
|
||||
from aiohttp import ClientResponseError
|
||||
from aiohttp_client_cache.session import CachedSession
|
||||
from aiohttp_client_cache import FileBackend
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
headers = {
|
||||
@@ -116,19 +117,38 @@ async def set_cover(book, data):
|
||||
book.set_cover("cover.jpg", await fetch_cover(data["cover"]))
|
||||
|
||||
|
||||
async def add_chapters(book, data):
|
||||
async def add_chapters(book, data, download_images: bool = False):
|
||||
chapters = []
|
||||
|
||||
for part in data["parts"]:
|
||||
content = await fetch_part_content(part["id"])
|
||||
title = part["title"]
|
||||
clean_title = slugify(title)
|
||||
|
||||
# Thanks https://eu17.proxysite.com/process.php?d=5VyWYcoQl%2BVF0BYOuOavtvjOloFUZz2BJ%2Fepiusk6Nz7PV%2B9i8rs7cFviGftrBNll%2B0a3qO7UiDkTt4qwCa0fDES&b=1
|
||||
chapter = epub.EpubHtml(
|
||||
title=title,
|
||||
file_name=f"{slugify(title)}.xhtml",
|
||||
file_name=f"{clean_title}.xhtml",
|
||||
lang=data["language"]["name"],
|
||||
)
|
||||
|
||||
if download_images:
|
||||
soup = BeautifulSoup(content, "lxml")
|
||||
async with CachedSession(cache=cache, headers=headers) as session:
|
||||
for idx, image in enumerate(soup.find_all("img")):
|
||||
if not image["src"]:
|
||||
continue
|
||||
async with session.get(image["src"]) as response:
|
||||
img = epub.EpubImage(
|
||||
media_type="image/jpeg",
|
||||
content=await response.read(),
|
||||
file_name=f"static/{clean_title}/{idx}.jpeg",
|
||||
)
|
||||
book.add_item(img)
|
||||
content = content.replace(
|
||||
str(image), f'<img src="static/{clean_title}/{idx}.jpeg"/>'
|
||||
)
|
||||
|
||||
chapter.set_content(f"<h1>{title}</h1>" + content)
|
||||
|
||||
chapters.append(chapter)
|
||||
|
||||
+18
-6
@@ -1,6 +1,6 @@
|
||||
from pathlib import Path
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import FileResponse, StreamingResponse
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.responses import FileResponse, HTMLResponse, StreamingResponse
|
||||
from ebooklib import epub
|
||||
from create_book import retrieve_story, set_cover, set_metadata, add_chapters, slugify
|
||||
import tempfile
|
||||
@@ -17,17 +17,29 @@ def home():
|
||||
|
||||
|
||||
@app.get("/download/{story_id}")
|
||||
async def download_book(story_id: int):
|
||||
async def download_book(story_id: int, download_images: bool = False):
|
||||
data = await retrieve_story(story_id)
|
||||
book = epub.EpubBook()
|
||||
|
||||
# Metadata and Cover are updated
|
||||
try:
|
||||
set_metadata(book, data)
|
||||
except KeyError:
|
||||
# raise HTTPException(
|
||||
# status_code=404,
|
||||
# detail='Story not found. Check the ID - Support is available on the <a href="https://discord.gg/P9RHC4KCwd" target="_blank">Discord</a>',
|
||||
# )
|
||||
# return FileResponse(BUILD_PATH / "index.html", status_code=404)
|
||||
return HTMLResponse(
|
||||
status_code=404,
|
||||
content='Story not found. Check the ID - Support is available on the <a href="https://discord.gg/P9RHC4KCwd" target="_blank">Discord</a>',
|
||||
)
|
||||
|
||||
await set_cover(book, data)
|
||||
# print("Metadata Downloaded")
|
||||
|
||||
# Chapters are downloaded
|
||||
async for title in add_chapters(book, data):
|
||||
async for title in add_chapters(book, data, download_images=download_images):
|
||||
# print(f"Part ({title}) downloaded")
|
||||
...
|
||||
|
||||
@@ -46,7 +58,7 @@ async def download_book(story_id: int):
|
||||
BytesIO(book_data),
|
||||
media_type="application/epub+zip",
|
||||
headers={
|
||||
"Content-Disposition": f'attachment; filename="{slugify(data["title"])}_{story_id}.epub"' # Thanks https://stackoverflow.com/a/72729058
|
||||
"Content-Disposition": f'attachment; filename="{slugify(data["title"])}_{story_id}_{"images" if download_images else ""}.epub"' # Thanks https://stackoverflow.com/a/72729058
|
||||
},
|
||||
)
|
||||
|
||||
@@ -57,4 +69,4 @@ app.mount("/", StaticFiles(directory=BUILD_PATH), "static")
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run(app, host="0.0.0.0", port=80)
|
||||
uvicorn.run(app, host="0.0.0.0", port=1112)
|
||||
@@ -2,4 +2,47 @@
|
||||
import "../app.pcss";
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<style>
|
||||
body {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600' viewBox='0 0 600 600'%3E%3Cpath fill='%239C92AC' fill-opacity='0.35' d='M600 325.1v-1.17c-6.5 3.83-13.06 7.64-14.68 8.64-10.6 6.56-18.57 12.56-24.68 19.09-5.58 5.95-12.44 10.06-22.42 14.15-1.45.6-2.96 1.2-4.83 1.9l-4.75 1.82c-9.78 3.75-14.8 6.27-18.98 10.1-4.23 3.88-9.65 6.6-16.77 8.84-1.95.6-3.99 1.17-6.47 1.8l-6.14 1.53c-5.29 1.35-8.3 2.37-10.54 3.78-3.08 1.92-6.63 3.26-12.74 5.03a384.1 384.1 0 0 1-4.82 1.36c-2.04.58-3.6 1.04-5.17 1.52a110.03 110.03 0 0 0-11.2 4.05c-2.7 1.15-5.5 3.93-8.78 8.4a157.68 157.68 0 0 0-6.15 9.2c-5.75 9.07-7.58 11.74-10.24 14.51a50.97 50.97 0 0 1-4.6 4.22c-2.33 1.9-10.39 7.54-11.81 8.74a14.68 14.68 0 0 0-3.67 4.15c-1.24 2.3-1.9 4.57-2.78 8.87-2.17 10.61-3.52 14.81-8.2 22.1-4.07 6.33-6.8 9.88-9.83 12.99-.47.48-.95.96-1.5 1.48l-3.75 3.56c-1.67 1.6-3.18 3.12-4.86 4.9a42.44 42.44 0 0 0-9.89 16.94c-2.5 8.13-2.72 15.47-1.76 27.22.47 5.82.51 6.36.51 8.18 0 10.51.12 17.53.63 25.78.24 4.05.56 7.8.97 11.22h.9c-1.13-9.58-1.5-21.83-1.5-37 0-1.86-.04-2.4-.52-8.26-.94-11.63-.72-18.87 1.73-26.85a41.44 41.44 0 0 1 9.65-16.55c1.67-1.76 3.18-3.27 4.83-4.85.63-.6 3.13-2.96 3.75-3.57a71.6 71.6 0 0 0 1.52-1.5c3.09-3.16 5.86-6.76 9.96-13.15 4.77-7.42 6.15-11.71 8.34-22.44.86-4.21 1.5-6.4 2.68-8.6.68-1.25 1.79-2.48 3.43-3.86 1.38-1.15 9.43-6.8 11.8-8.72 1.71-1.4 3.26-2.81 4.7-4.3 2.72-2.85 4.56-5.54 10.36-14.67a156.9 156.9 0 0 1 6.1-9.15c3.2-4.33 5.9-7.01 8.37-8.07 3.5-1.5 7.06-2.77 11.1-4.02a233.84 233.84 0 0 1 7.6-2.2l2.38-.67c6.19-1.79 9.81-3.16 12.98-5.15 2.14-1.33 5.08-2.33 10.27-3.65l6.14-1.53c2.5-.63 4.55-1.2 6.52-1.82 7.24-2.27 12.79-5.06 17.15-9.05 4.05-3.72 9-6.2 18.66-9.9l4.75-1.82c1.87-.72 3.39-1.31 4.85-1.91 10.1-4.15 17.07-8.32 22.76-14.4 6.05-6.45 13.95-12.4 24.49-18.92 1.56-.96 7.82-4.6 14.15-8.33v-64.58c-4 8.15-8.52 14.85-12.7 17.9-2.51 1.82-5.38 4.02-9.04 6.92a1063.87 1063.87 0 0 0-6.23 4.98l-1.27 1.02a2309.25 2309.25 0 0 1-4.87 3.9c-7.55 6-12.9 10.05-17.61 13.19-3.1 2.06-3.86 2.78-8.06 7.13-5.84 6.07-11.72 8.62-29.15 10.95-11.3 1.5-20.04 4.91-30.75 11.07-1.65.94-7.27 4.27-6.97 4.1-2.7 1.58-4.69 2.69-6.64 3.66-5.63 2.8-10.47 4.17-15.71 4.17-17.13 0-41.44 11.51-51.63 22.83-12.05 13.4-31.42 27.7-45.25 31.16-7.4 1.85-11.85 7.05-14.04 14.69-1.26 4.4-1.58 8.28-1.58 13.82 0 .82.01.98.24 3.63.45 5.18.35 8.72-.77 13.26-1.53 6.2-4.89 12.6-10.59 19.43-13.87 16.65-22.88 46.58-22.88 71.68 0 2.39.02 4.26.06 8.75.12 10.8.1 15.8-.22 21.95-.56 11.18-2.09 20.73-5 29.3h-1.05c2.94-8.56 4.49-18.12 5.05-29.35.31-6.13.34-11.1.22-21.9-.04-4.48-.06-6.36-.06-8.75 0-25.32 9.07-55.47 23.12-72.32 5.6-6.72 8.88-12.99 10.38-19.03 1.09-4.4 1.18-7.85.74-12.93-.23-2.7-.24-2.86-.24-3.72 0-5.62.32-9.57 1.62-14.1 2.28-7.95 6.97-13.44 14.76-15.39 13.6-3.4 32.82-17.59 44.75-30.84C409 360.14 433.58 348.5 451 348.5c5.07 0 9.77-1.33 15.26-4.07 1.93-.96 3.9-2.05 6.58-3.62-.3.18 5.33-3.16 6.98-4.11 10.82-6.21 19.66-9.67 31.11-11.2 17.23-2.3 22.9-4.75 28.57-10.64 4.25-4.41 5.04-5.16 8.22-7.28 4.68-3.11 10.01-7.14 17.55-13.14a1113.33 1113.33 0 0 0 4.86-3.89l1.28-1.02a4668.54 4668.54 0 0 1 6.23-4.98c3.67-2.9 6.55-5.12 9.07-6.95 4.37-3.19 9.16-10.56 13.29-19.4v66.9zm0-116.23c-.62.01-1.27.06-1.95.13-6.13.63-13.83 3.45-21.83 7.45-3.64 1.82-8.46 2.67-14.17 2.71-4.7.04-9.72-.47-14.73-1.33-1.7-.3-3.26-.61-4.67-.93a31.55 31.55 0 0 0-3.55-.57 273.4 273.4 0 0 0-16.66-.88c-10.42-.16-17.2.74-17.97 2.73-.38.97.6 2.55 3.03 4.87 1.01.97 2.22 2.03 4.04 3.55a1746.07 1746.07 0 0 0 4.79 4.02c1.39 1.2 3.1 1.92 5.5 2.5.7.16.86.2 2.64.54 3.53.7 5.03 1.25 6.15 2.63 1.41 1.76 1.4 4.54-.15 8.88-2.44 6.83-5.72 10.05-10.19 10.33-3.63.23-7.6-1.29-14.52-5.06-4.53-2.47-6.82-7.3-8.32-15.26-.17-.87-.32-1.78-.5-2.86l-.43-2.76c-1.05-6.58-1.9-9.2-3.73-10.11-.81-.4-1.59-.74-2.36-1-2.27-.77-4.6-1.02-8.1-.92-2.29.07-14.7 1-13.77.93-20.55 1.37-28.8 5.05-37.09 14.99a133.07 133.07 0 0 0-4.25 5.44l-2.3 3.09-2.51 3.32c-4.1 5.36-7.06 8.48-10.39 11.12-.65.52-1.33 1.04-2.13 1.62l-4.11 2.94a106.8 106.8 0 0 0-5.16 3.99c-4.55 3.74-9.74 8.6-16.25 15.38-8.25 8.58-11.78 13.54-11.7 15.95.07 1.65 1.64 2.11 6.79 2.38 1.61.09 2.15.12 2.98.2 2.95.24 5.09.73 6.81 1.68 7.48 4.15 11.63 7.26 13.95 11.58 3.3 6.15.8 12.88-8.89 20.26-8.28 6.3-11.1 10.37-11.31 14.96-.06 1.17 0 1.93.26 4.43.69 6.47.25 10.65-2.8 17.42a44.23 44.23 0 0 1-4.16 7.53c-2.82 3.97-5.47 5.74-10.6 7.69-.43.16-3.34 1.23-4.27 1.59-1.8.68-3.38 1.36-5.01 2.14-4.18 2-8.4 4.6-13.1 8.24-8.44 6.51-13.23 14.56-15.98 25.06-1.1 4.2-1.55 6.81-2.8 15.21-1.26 8.6-2.17 12.64-4.08 16.55-2.1 4.28-11.93 26.59-12.97 28.88a382.7 382.7 0 0 1-6.37 13.41c-4.07 8.11-7.61 14.07-10.73 17.81-5.38 6.46-8.98 14.37-13.77 28.42a810.14 810.14 0 0 0-1.89 5.6c-1.8 5.35-2.96 8.6-4.26 11.85-6.13 15.32-25.43 26.31-46.46 26.31-11.2 0-20.58-2.74-31.02-8.55-5.6-3.13-4.55-2.42-22.26-14.54-14.33-9.8-17.7-10.73-20.47-6.9-.37.5-1.81 2.74-1.83 2.77a52.24 52.24 0 0 1-4.94 5.9c-.73.79-5.52 5.87-6.97 7.45-2.38 2.6-4.3 4.81-5.98 6.93a45.6 45.6 0 0 0-5.08 Line truncated
|
||||
}
|
||||
</style>
|
||||
</svelte:head>
|
||||
|
||||
<slot />
|
||||
|
||||
<footer
|
||||
class="footer footer-center p-4 bg-base-300 text-base-content bottom-0 fixed"
|
||||
>
|
||||
<aside>
|
||||
<div class="grid grid-cols-3 max-w-lg w-full">
|
||||
<a
|
||||
href="https://liberapay.com/TheOnlyWayUp/"
|
||||
target="_blank"
|
||||
class="link"
|
||||
data-umami-event="Footer Donate">Donate</a
|
||||
>
|
||||
<a
|
||||
href="https://rambhat.la"
|
||||
target="_blank"
|
||||
class="link"
|
||||
data-umami-event="Footer AboutMe">About Me</a
|
||||
>
|
||||
<a
|
||||
href="https://discord.gg/P9RHC4KCwd"
|
||||
target="_blank"
|
||||
class="link"
|
||||
data-umami-event="Footer Discord">Discord</a
|
||||
>
|
||||
</div>
|
||||
<p>
|
||||
Copyright © 2024 - All rights reserved by <a
|
||||
href="https://rambhat.la"
|
||||
class="link"
|
||||
target="_blank"
|
||||
data-umami-event="CopyrightHolder">Dhanush R</a
|
||||
>
|
||||
</p>
|
||||
</aside>
|
||||
</footer>
|
||||
@@ -1,19 +1,27 @@
|
||||
<script>
|
||||
let story_id = "";
|
||||
let download_images = false;
|
||||
let after_download_page = true;
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="hero min-h-screen bg-base-200">
|
||||
<div class="hero-content flex-col lg:flex-row-reverse">
|
||||
<div class="hero min-h-screen">
|
||||
<div
|
||||
class="hero-content flex-col lg:flex-row-reverse glass p-16 rounded shadow-sm"
|
||||
>
|
||||
{#if !after_download_page}
|
||||
<div class="text-center lg:text-left lg:p-10">
|
||||
<h1
|
||||
class="font-extrabold text-transparent text-5xl bg-clip-text bg-gradient-to-r to-pink-600 via-yellow-600 from-red-700"
|
||||
>
|
||||
Wattpad Downloader
|
||||
</h1>
|
||||
<p class="py-6">
|
||||
Download your favourite books as EPUBs with a single click!
|
||||
<p class="pt-6 text-lg">
|
||||
Download your favourite books with a single click!
|
||||
</p>
|
||||
<ul class="pt-4 list list-inside text-xl">
|
||||
<li>06/24 - 🎉 Image Downloading!</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card shrink-0 w-full max-w-sm shadow-2xl bg-base-100">
|
||||
<form class="card-body">
|
||||
@@ -40,18 +48,58 @@
|
||||
<a
|
||||
class="btn btn-primary rounded-l-none"
|
||||
class:btn-disabled={!story_id}
|
||||
href={`/download/${story_id}`}
|
||||
data-umami-event="Download"
|
||||
download
|
||||
onclick="AfterDownloadModal.showModal()">Download</a
|
||||
href={`/download/${story_id}${download_images ? "?download_images=true" : ""}`}
|
||||
on:click={() => (after_download_page = true)}>Download</a
|
||||
>
|
||||
<label class="cursor-pointer label">
|
||||
<span class="label-text"
|
||||
>Include Images (<strong>Slower Download</strong>)</span
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checkbox-warning shadow-md"
|
||||
bind:checked={download_images}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<button data-feedback-fish class="link pb-2" data-umami-event="Feedback"
|
||||
>Feedback</button
|
||||
<button
|
||||
data-feedback-fish
|
||||
class="link pb-4"
|
||||
data-umami-event="Feedback">Feedback</button
|
||||
>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="text-center max-w-4xl">
|
||||
<h1 class="font-bold text-3xl">
|
||||
Your download has <span
|
||||
class="text-transparent bg-clip-text bg-gradient-to-r to-pink-600 via-yellow-600 from-red-700"
|
||||
>Started</span
|
||||
>
|
||||
</h1>
|
||||
<div class="py-4 space-y-2">
|
||||
<p class="text-2xl">
|
||||
If you found this site useful, please consider <a
|
||||
href="https://github.com/TheOnlyWayUp/WattpadDownloader"
|
||||
target="_blank"
|
||||
class="link"
|
||||
data-umami-event="Star">starring the project</a
|
||||
> to support WattpadDownloader.
|
||||
</p>
|
||||
<p class="text-lg pt-2">
|
||||
You can also join us on <a
|
||||
href="https://discord.gg/P9RHC4KCwd"
|
||||
target="_blank"
|
||||
class="link"
|
||||
data-umami-event="Discord">discord</a
|
||||
>, where we release features early and discuss updates.
|
||||
</p>
|
||||
</div>
|
||||
<a href="/" class="btn btn-outline btn-lg mt-10">Download More</a>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -90,78 +138,3 @@
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<dialog id="AfterDownloadModal" class="modal">
|
||||
<div class="modal-box">
|
||||
<h3 class="font-bold text-lg">Your download has started</h3>
|
||||
<div class="py-4 space-y-2">
|
||||
<p class="text-xl">
|
||||
Hi, thanks for using my site! If you found it useful, please consider <a
|
||||
href="https://liberapay.com/TheOnlyWayUp/"
|
||||
target="_blank"
|
||||
class="link"
|
||||
data-umami-event="Donate">donating</a
|
||||
> to keep this project alive.
|
||||
</p>
|
||||
<p>
|
||||
You can also join us on <a
|
||||
href="https://discord.gg/P9RHC4KCwd"
|
||||
target="_blank"
|
||||
class="link"
|
||||
data-umami-event="Discord">discord</a
|
||||
>, where we discuss updates and features.
|
||||
</p>
|
||||
<p class="text-lg">
|
||||
Please take a look at <a
|
||||
href="https://rambhat.la"
|
||||
class="link"
|
||||
data-umami-event="My Work">my work</a
|
||||
>!
|
||||
</p>
|
||||
</div>
|
||||
<div class="pt-2">
|
||||
<form method="dialog">
|
||||
<!-- if there is a button in form, it will close the modal -->
|
||||
<button
|
||||
class="btn w-full btn-sm btn-ghost"
|
||||
data-umami-event="AfterDownloadModal Close">Close</button
|
||||
>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<footer
|
||||
class="footer footer-center p-4 bg-base-300 text-base-content bottom-0 fixed"
|
||||
>
|
||||
<aside>
|
||||
<div class="grid grid-cols-3 max-w-lg w-full">
|
||||
<a
|
||||
href="https://liberapay.com/TheOnlyWayUp/"
|
||||
target="_blank"
|
||||
class="link"
|
||||
data-umami-event="Footer Donate">Donate</a
|
||||
>
|
||||
<a
|
||||
href="https://rambhat.la"
|
||||
target="_blank"
|
||||
class="link"
|
||||
data-umami-event="Footer AboutMe">About Me</a
|
||||
>
|
||||
<a
|
||||
href="https://discord.gg/P9RHC4KCwd"
|
||||
target="_blank"
|
||||
class="link"
|
||||
data-umami-event="Footer Discord">Discord</a
|
||||
>
|
||||
</div>
|
||||
<p>
|
||||
Copyright © 2024 - All rights reserved by <a
|
||||
href="https://rambhat.la"
|
||||
class="link"
|
||||
target="_blank"
|
||||
data-umami-event="CopyrightHolder">Dhanush R</a
|
||||
>
|
||||
</p>
|
||||
</aside>
|
||||
</footer>
|
||||
Reference in new issue
Block a user