Skip to content

Commit

Permalink
Update 1.1.0 Merge pull request #200 from MangaManagerORG/develop
Browse files Browse the repository at this point in the history
Update 1.1.0
  • Loading branch information
ThePromidius authored Jan 27, 2024
2 parents 605ff65 + ca0c058 commit 60ff6bb
Show file tree
Hide file tree
Showing 71 changed files with 973 additions and 439 deletions.
3 changes: 3 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 3 additions & 13 deletions .idea/runConfigurations/Build.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/runConfigurations/MangaManager.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions .idea/runConfigurations/MangaManager_DEBUG.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions .idea/runConfigurations/MangaManager_TRACE.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion DEVELOPMENT.MD
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,16 @@ After that you can now create the build with the command below
If you can not run the build make sure all requirements are installed.
Pyinstaller does not use the virtual env requirements. So make sure the base python has them installed
Some of the requirements that gave me issues are:
- `chardet`
- `chardet`

# QuickGuides
## Adding a setting

### Is this a main app/default setting?

If so go into src.Settings.SettingsDefault and add it there.

Say i want to add a toggle to enable darkmode

I add the key i'll use under Main section. `{"darkmode_enabled":False}` I want it opt-in so i set it to False
Lets add the setting in the settings menu. Head to src.MetadataManager.GUI.windows.SettingsWindow. Add your key in the corresponding section using the SettingControl of your choosing. In my case its a boolean. So SettingControlType.Bool
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ ENV GUIAUTOSTART=true

WORKDIR /tmp
COPY requirements.txt /tmp/
COPY requirements.txt /app/

# Copy App
COPY --chown=$UID:$GID [ "/MangaManager", "/app" ]
Expand All @@ -22,6 +23,7 @@ RUN apt-get update && \
xubuntu-default-settings \
xubuntu-icon-theme \
unrar\
# git\
# Python \
idle-python3.11 \
python3-tk \
Expand Down
39 changes: 39 additions & 0 deletions MangaManager/Extensions/CoverDownloader/CoverData.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import dataclasses
from pathlib import Path
from os.path import splitext
@dataclasses.dataclass
class SeriesCoverData:
normalized_name:str

class CoverData:
# filename:str
# extension:str
#
# volume:str
# locale:str
@property
def dest_filename(self):
"""
The final filename
:return:
"""
return f"Cover{'_Vol.'+str(self.volume).zfill(2) if self.volume else ''}{'_' + self.locale if self.locale else ''}{self.extension}"


def __init__(self,source_filename=None,volume=None,locale=None):

self.source_filename=source_filename
if source_filename:
self.filename, self.extension = splitext(self.source_filename)
else:
self.filename, self.extension = None, None
self.volume=volume
self.locale=locale


def from_cover_data(self,cover_data):
self.source_filename = cover_data.get("attributes").get("fileName")
self.filename, self.extension = splitext(self.source_filename)
self.volume = cover_data.get("attributes").get("volume")
self.locale = cover_data.get("attributes").get("locale")
return self
151 changes: 140 additions & 11 deletions MangaManager/Extensions/CoverDownloader/CoverDownloader.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,156 @@
from tkinter import Label, Frame, Entry

# import tkinter
# from idlelib.tooltip import Hovertip
# from idlelib.tooltip import Hovertip
import asyncio
import logging
import urllib.request
import os
import platform
import subprocess
from enum import StrEnum
from pathlib import Path
from tkinter import Frame, Label, StringVar
from tkinter.ttk import Entry, Button, Frame
import slugify
import requests

from Extensions.CoverDownloader.CoverData import CoverData
from Extensions.CoverDownloader.MangaDex import parse_mangadex_id
from Extensions.CoverDownloader.exceptions import UrlNotFound
from Extensions.IExtensionApp import IExtensionApp
from src.MetadataManager.GUI.widgets import ProgressBarWidget
# from src.MetadataManager.GUI.tooltip import ToolTip
from src.Settings import Settings, SettingHeading, SettingSection, SettingControl, SettingControlType

logger = logging.getLogger()
def get_cover_from_source_dummy() -> list:
...


class CoverDownloader():#IExtensionApp):
class CoverDownloaderSetting(StrEnum):
ForceOverwrite = "force_overwrite" # If existing covers should be re-downloaded and overwritten
class CoverDownloader(IExtensionApp):
name = "Cover Downloader"
embedded_ui = True

def init_settings(self):

self.settings = [
SettingSection(self.name,self.name,[
SettingControl(
key=CoverDownloaderSetting.ForceOverwrite,
name="Force Overwrite",
control_type=SettingControlType.Bool,
value=False,
tooltip="Enable if existing covers should be re-downloaded and overwritten"
)
])
]
super().init_settings()

@property
def output_folder(self):
return Settings().get(SettingHeading.Main, 'covers_folder_path')

def serve_gui(self):
if not self.master:
return Exception("Tried to initialize ui with no master window")
self.url_var = StringVar(name="mdex_cover_url")
self.url_var.trace("w",self.get_series_data)

self.dest_path_var = StringVar(name="dest_path",value=str(Path((self.output_folder or Path(Path.home(),"Pictures","Manga Covers")),
'<Manga Name Folder>')))
Label(self.master,text="MangaManager will download all availabe images from").pack()
# self.frame_3 = Frame(frame1)
Label(self.master, text='MANGADEX MANGA ID / URL').pack(side='top')
Entry(master=self.master,textvariable=self.url_var).pack(side='top')

Label(self.master, text="to the folder:").pack()
label_path = Label(self.master,textvariable=self.dest_path_var)
label_path.pack(pady="10 30", side='top')

self.button_1 = Button(self.master, text='Correct! Start!', state="disabled", command=self.process_download)
self.button_1.pack(side='top')
self.button_explorer = Button(self.master, text='Open explorer', command=self.open_explorer)
self.pb = ProgressBarWidget(self.master)

def process_download(self):
try:
self.download()
except Exception as e:
logger.exception("Error downloading")
finally:
self.button_1.configure(text="DONE", state="disabled")
self.show_open_explorer_btn()

def show_open_explorer_btn(self):
self.button_explorer.pack(side='top')
def hide_open_explorer_btn(self):
self.button_explorer.pack_forget()

def open_explorer(self):

path = self.dest_path_var.get()
if platform.system() == "Windows":
os.startfile(path)
elif platform.system() == "Darwin":
subprocess.Popen(["open", path])
else:
subprocess.Popen(["xdg-open", path])
...





frame = Frame(self.master)
frame.pack()
def get_series_data(self,*_):
mdex_id = parse_mangadex_id(self.url_var.get())
if mdex_id is None:
return
self.hide_open_explorer_btn()
self.button_1.configure(text="Correct! Start", state="normal")
# self.show_open_explorer_btn()

Label(frame, text="Manga identifier").pack()
Entry(frame).pack()
# Combobox(frame, state="readonly",values=sources_factory["CoverSources"]).pack()
logger.debug(f"Parsed mdex id: '{mdex_id}'")
data = {"manga[]": [mdex_id], "includes[]": ["manga"], "limit": 50}
# Request the list of covers in the prrovided manga
r = requests.get(f"https://api.mangadex.org/cover", params=data)

covers = get_cover_from_source_dummy()
if r.status_code != 200:
logger.warning(f"Page responded with {r.status_code}",extra={"url":r.url})
return
# raise UrlNotFound(r.url)
data = r.json().get("data")
cover_attributes = data[0].get("relationships")[0].get("attributes")

# Get title
ja_title = list(filter(lambda p: p.get("ja-ro"),
cover_attributes.get("altTitles")))
if ja_title:
ja_title = ja_title[0].get("ja-ro")
full_name = (ja_title or cover_attributes.get("title").get("en"))
normalized_manga_name = slugify.slugify(full_name[:50])

# Get final path where images will be saved
self.destination_dirpath = Path((self.output_folder or Path(Path.home(), "Pictures", "Manga Covers")),normalized_manga_name)

# Update ui path
self.dest_path_var.set(str(self.destination_dirpath))
self.update()
self.cur_id = mdex_id
self.cur_data = data
def download(self):
self.pb.start(len(self.cur_data))
self.destination_dirpath.mkdir(parents=True, exist_ok=True)
for i,cover_data in enumerate(self.cur_data):
cover = CoverData().from_cover_data(cover_data)
image_path = Path(self.destination_dirpath, cover.dest_filename)
if not image_path.exists() or Settings().get(self.name,CoverDownloaderSetting.ForceOverwrite):
image_url = f"https://mangadex.org/covers/{self.cur_id}/{cover.source_filename}"

urllib.request.urlretrieve(image_url, image_path)
logger.debug(f"Downloaded '{image_path}'")
else:
logger.info(f"Skipped https://mangadex.org/covers/{self.cur_id}/{cover.source_filename} -> Already exists")
self.pb.increase_failed()
self.pb.increase_processed()
self.pb.stop()
self.update()
Loading

0 comments on commit 60ff6bb

Please sign in to comment.