Merge pull request #5 from TheOnlyWayUp/redesign

Update UI
This commit is contained in:
Dhanush R
2024-06-25 23:53:47 +05:30
committed by GitHub
6 changed files with 181 additions and 130 deletions
+3
View File
@@ -9,6 +9,8 @@ asttokens==2.4.1
async-timeout==4.0.3 async-timeout==4.0.3
attrs==23.1.0 attrs==23.1.0
backoff==2.2.1 backoff==2.2.1
beautifulsoup4==4.12.3
bs4==0.0.2
click==8.1.7 click==8.1.7
comm==0.2.0 comm==0.2.0
debugpy==1.8.0 debugpy==1.8.0
@@ -48,6 +50,7 @@ pyzmq==25.1.2
rich==13.7.0 rich==13.7.0
six==1.16.0 six==1.16.0
sniffio==1.3.0 sniffio==1.3.0
soupsieve==2.5
stack-data==0.6.3 stack-data==0.6.3
starlette==0.32.0.post1 starlette==0.32.0.post1
tornado==6.4 tornado==6.4
+22 -2
View File
@@ -6,6 +6,7 @@ import backoff
from aiohttp import ClientResponseError from aiohttp import ClientResponseError
from aiohttp_client_cache.session import CachedSession from aiohttp_client_cache.session import CachedSession
from aiohttp_client_cache import FileBackend from aiohttp_client_cache import FileBackend
from bs4 import BeautifulSoup
headers = { headers = {
@@ -116,19 +117,38 @@ async def set_cover(book, data):
book.set_cover("cover.jpg", await fetch_cover(data["cover"])) 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 = [] chapters = []
for part in data["parts"]: for part in data["parts"]:
content = await fetch_part_content(part["id"]) content = await fetch_part_content(part["id"])
title = part["title"] title = part["title"]
clean_title = slugify(title)
# Thanks https://eu17.proxysite.com/process.php?d=5VyWYcoQl%2BVF0BYOuOavtvjOloFUZz2BJ%2Fepiusk6Nz7PV%2B9i8rs7cFviGftrBNll%2B0a3qO7UiDkTt4qwCa0fDES&b=1 # Thanks https://eu17.proxysite.com/process.php?d=5VyWYcoQl%2BVF0BYOuOavtvjOloFUZz2BJ%2Fepiusk6Nz7PV%2B9i8rs7cFviGftrBNll%2B0a3qO7UiDkTt4qwCa0fDES&b=1
chapter = epub.EpubHtml( chapter = epub.EpubHtml(
title=title, title=title,
file_name=f"{slugify(title)}.xhtml", file_name=f"{clean_title}.xhtml",
lang=data["language"]["name"], 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) chapter.set_content(f"<h1>{title}</h1>" + content)
chapters.append(chapter) chapters.append(chapter)
+18 -6
View File
@@ -1,6 +1,6 @@
from pathlib import Path from pathlib import Path
from fastapi import FastAPI from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse, StreamingResponse from fastapi.responses import FileResponse, HTMLResponse, StreamingResponse
from ebooklib import epub from ebooklib import epub
from create_book import retrieve_story, set_cover, set_metadata, add_chapters, slugify from create_book import retrieve_story, set_cover, set_metadata, add_chapters, slugify
import tempfile import tempfile
@@ -17,17 +17,29 @@ def home():
@app.get("/download/{story_id}") @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) data = await retrieve_story(story_id)
book = epub.EpubBook() book = epub.EpubBook()
# Metadata and Cover are updated # Metadata and Cover are updated
try:
set_metadata(book, data) 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) await set_cover(book, data)
# print("Metadata Downloaded") # print("Metadata Downloaded")
# Chapters are 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") # print(f"Part ({title}) downloaded")
... ...
@@ -46,7 +58,7 @@ async def download_book(story_id: int):
BytesIO(book_data), BytesIO(book_data),
media_type="application/epub+zip", media_type="application/epub+zip",
headers={ 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__": if __name__ == "__main__":
import uvicorn import uvicorn
uvicorn.run(app, host="0.0.0.0", port=80) uvicorn.run(app, host="0.0.0.0", port=1112)
File diff suppressed because one or more lines are too long
+57 -84
View File
@@ -1,19 +1,27 @@
<script> <script>
let story_id = ""; let story_id = "";
let download_images = false;
let after_download_page = true;
</script> </script>
<div> <div>
<div class="hero min-h-screen bg-base-200"> <div class="hero min-h-screen">
<div class="hero-content flex-col lg:flex-row-reverse"> <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"> <div class="text-center lg:text-left lg:p-10">
<h1 <h1
class="font-extrabold text-transparent text-5xl bg-clip-text bg-gradient-to-r to-pink-600 via-yellow-600 from-red-700" 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 Wattpad Downloader
</h1> </h1>
<p class="py-6"> <p class="pt-6 text-lg">
Download your favourite books as EPUBs with a single click! Download your favourite books with a single click!
</p> </p>
<ul class="pt-4 list list-inside text-xl">
<li>06/24 - 🎉 Image Downloading!</li>
</ul>
</div> </div>
<div class="card shrink-0 w-full max-w-sm shadow-2xl bg-base-100"> <div class="card shrink-0 w-full max-w-sm shadow-2xl bg-base-100">
<form class="card-body"> <form class="card-body">
@@ -40,18 +48,58 @@
<a <a
class="btn btn-primary rounded-l-none" class="btn btn-primary rounded-l-none"
class:btn-disabled={!story_id} class:btn-disabled={!story_id}
href={`/download/${story_id}`}
data-umami-event="Download" data-umami-event="Download"
download href={`/download/${story_id}${download_images ? "?download_images=true" : ""}`}
onclick="AfterDownloadModal.showModal()">Download</a 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> </div>
</form> </form>
<button data-feedback-fish class="link pb-2" data-umami-event="Feedback" <button
>Feedback</button data-feedback-fish
class="link pb-4"
data-umami-event="Feedback">Feedback</button
> >
</div> </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> </div>
</div> </div>
@@ -90,78 +138,3 @@
<button>close</button> <button>close</button>
</form> </form>
</dialog> </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>