Repos / pytaku / 75a9c8aa47
commit 75a9c8aa47dd6bbb6496d5e3d205839a4020c134
Author: Bùi Thành Nhân <hi@imnhan.com>
Date: Sun Aug 9 17:04:06 2020 +0700
mangasee title/follows view
diff --git a/src/mangoapi/base_site.py b/src/mangoapi/base_site.py
index 79fa6d1..b7f6df2 100644
--- a/src/mangoapi/base_site.py
+++ b/src/mangoapi/base_site.py
@@ -20,6 +20,14 @@ def get_chapter(self, chapter_id):
def search_title(self, query):
pass
+ @abstractmethod
+ def title_cover(self, title_id, cover_ext):
+ pass
+
+ @abstractmethod
+ def title_source_url(self, title_id):
+ pass
+
# optional abstract method
def login(self, username, password):
raise NotImplementedError()
diff --git a/src/mangoapi/mangadex.py b/src/mangoapi/mangadex.py
index cb5c07b..3ba5cfe 100644
--- a/src/mangoapi/mangadex.py
+++ b/src/mangoapi/mangadex.py
@@ -95,6 +95,12 @@ def login(self, username, password):
assert md_resp.status_code == 200, md_resp.text
return dict(md_resp.cookies)
+ def title_cover(self, title_id, cover_ext):
+ return f"https://mangadex.org/images/manga/{title_id}.{cover_ext}"
+
+ def title_source_url(self, title_id):
+ return f"https://mangadex.org/manga/{title_id}"
+
# Titles regex slightly adapted from https://github.com/md-y/mangadex-full-api
# Thanks!
diff --git a/src/mangoapi/mangasee.py b/src/mangoapi/mangasee.py
index 9fd25fe..36e5cae 100644
--- a/src/mangoapi/mangasee.py
+++ b/src/mangoapi/mangasee.py
@@ -1,10 +1,16 @@
import json
+import re
import apsw
import requests
from mangoapi.base_site import Site
+regexes = {
+ "title_name": re.compile(r"<title>\s*([^|]+) | MangaSee</title>"),
+ "title_chapters": re.compile(r"vm\.Chapters = (\[[^\]]+\])"),
+}
+
class Mangasee(Site):
search_table = None
@@ -13,7 +19,30 @@ def __init__(self, keyval_store=None):
self.keyval_store = keyval_store
def get_title(self, title_id):
- pass
+ resp = requests.get(f"https://mangasee123.com/manga/{title_id}", timeout=3)
+ assert resp.status_code == 200
+ html = resp.text
+ name = regexes["title_name"].search(html).group(1).strip()
+ chapters_str = regexes["title_chapters"].search(html).group(1)
+ chapters = [
+ {
+ "id": ch["Chapter"],
+ "name": ch["ChapterName"],
+ "volume": "",
+ "groups": [],
+ **_parse_chapter_number(ch["Chapter"]),
+ }
+ for ch in json.loads(chapters_str)
+ ]
+ return {
+ "id": title_id,
+ "name": name,
+ "site": "mangasee",
+ "cover_ext": "jpg",
+ "chapters": chapters,
+ "alt_names": [],
+ "descriptions": [],
+ }
def get_chapter(self, chapter_id):
pass
@@ -60,6 +89,12 @@ def search_title(self, query):
for row in self.search_table.search(query)
]
+ def title_cover(self, title_id, cover_ext):
+ return f"https://cover.mangabeast01.com/cover/{title_id}.jpg"
+
+ def title_source_url(self, title_id):
+ return f"https://mangasee123.com/manga/{title_id}"
+
class SearchTable:
def __init__(self, titles: list):
@@ -84,3 +119,27 @@ def search(self, query):
return self.db.cursor().execute(
"SELECT id, name FROM titles(?) ORDER BY rank;", (query,)
)
+
+
+def _parse_chapter_number(e):
+ """
+ Mangasee author tries to be clever with obtuse chapter numbers that must be decoded
+ via javascript:
+
+ (vm.ChapterDisplay = function (e) {
+ var t = parseInt(e.slice(1, -1)),
+ n = e[e.length - 1];
+ return 0 == n ? t : t + "." + n;
+ })
+
+ Example: vm.ChapterDisplay('100625') === '62.5'
+
+ No idea why tbh.
+ """
+ major = int(e[1:-1])
+ minor = int(e[-1])
+ return {
+ "num_major": major,
+ "num_minor": minor,
+ "number": str(major) if not minor else f"{major}.{minor}",
+ }
diff --git a/src/pytaku/main.py b/src/pytaku/main.py
index 2642a42..ade49d3 100644
--- a/src/pytaku/main.py
+++ b/src/pytaku/main.py
@@ -27,7 +27,13 @@
unfollow,
verify_username_password,
)
-from .source_sites import get_chapter, get_title, search_title_all_sites
+from .source_sites import (
+ get_chapter,
+ get_title,
+ search_title_all_sites,
+ title_cover,
+ title_source_url,
+)
config.load()
@@ -50,6 +56,8 @@ def home_view():
@require_login
def follows_view():
titles = get_followed_titles(session["user"]["id"])
+ for title in titles:
+ title["cover"] = title_cover(title["site"], title["id"], title["cover_ext"])
return render_template("follows.html", titles=titles)
@@ -169,12 +177,14 @@ def title_view(site, title_id):
title = load_title(site, title_id, user_id=user_id)
if not title:
print("Getting title", title_id)
- title = get_title(title_id)
+ title = get_title(site, title_id)
print("Saving title", title_id, "to db")
save_title(title)
else:
print("Loading title", title_id, "from db")
title["site"] = site
+ title["cover"] = title_cover(site, title_id, title["cover_ext"])
+ title["source_url"] = title_source_url(site, title_id)
return render_template("title.html", **title)
diff --git a/src/pytaku/persistence.py b/src/pytaku/persistence.py
index a97ae51..82f2df8 100644
--- a/src/pytaku/persistence.py
+++ b/src/pytaku/persistence.py
@@ -37,7 +37,7 @@ def save_title(title):
{
"id": title["id"],
"name": title["name"],
- "site": "mangadex",
+ "site": title["site"],
"cover_ext": title["cover_ext"],
"chapters": json.dumps(title["chapters"]),
"alt_names": json.dumps(title["alt_names"]),
diff --git a/src/pytaku/source_sites.py b/src/pytaku/source_sites.py
index d97f43b..44577b6 100644
--- a/src/pytaku/source_sites.py
+++ b/src/pytaku/source_sites.py
@@ -38,12 +38,17 @@ def search_title(site_name, query):
return _get_site(site_name).search_title(query)
+def title_cover(site_name, title_id, cover_ext):
+ return _get_site(site_name).title_cover(title_id, cover_ext)
+
+
+def title_source_url(site_name, title_id):
+ return _get_site(site_name).title_source_url(title_id)
+
+
def search_title_all_sites(query):
"""
Returns dict in the form of {site_name: List[Title]}
I should really look into proper type annotations huh.
"""
- return {
- site_name: search_title(site_name, query)
- for site_name in ("mangasee", "mangadex")
- }
+ return {site_name: search_title(site_name, query) for site_name in ("mangasee",)}
diff --git a/src/pytaku/templates/follows.html b/src/pytaku/templates/follows.html
index ac6dda3..ee57dc9 100644
--- a/src/pytaku/templates/follows.html
+++ b/src/pytaku/templates/follows.html
@@ -23,6 +23,7 @@
.cover {
border: 1px solid #777;
margin-right: .5rem;
+ max-width: 150px;
}
.cover:hover {
box-shadow: 0 0 3px black;
@@ -48,6 +49,7 @@
.chapter:last-child::after {
content: '← resume here';
background-color: cornsilk;
+ white-space: nowrap;
}
.group {
@@ -73,7 +75,7 @@
<div>
<a href="{{ title_url }}">
<img class="cover"
- src="https://mangadex.org/images/manga/{{ title['id'] }}.large.jpg"
+ src="{{ title['cover'] }}"
alt="{{ title['name'] }}" />
</a>
</div>
diff --git a/src/pytaku/templates/title.html b/src/pytaku/templates/title.html
index c18cae2..e39ea1d 100644
--- a/src/pytaku/templates/title.html
+++ b/src/pytaku/templates/title.html
@@ -37,10 +37,10 @@ <h1>{{ name }}</h1>
{{ ibutton(left_icon='bookmark', text=ftext, color=fcolor, title=ftitle) }}
</form>
{% endif %}
- {{ ibutton(href='https://mangadex.org/manga/' + id, right_icon='arrow-up-right', text='Source site', color='blue', title='Go to source site') }}
+ {{ ibutton(href=source_url, right_icon='arrow-up-right', text='Source site', color='blue', title='Go to source site') }}
</div>
-<img class="cover" src="https://mangadex.org/images/manga/{{ id }}.{{ cover_ext }}" alt="cover" />
+<img class="cover" src="{{ cover }}" alt="cover" />
{% if chapters %}
<table>