Adding src/ folder? no idea what happened
This commit is contained in:
parent
c8886d69ed
commit
830af873b9
245
src/app.py
Normal file
245
src/app.py
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
from nicegui import ui, app
|
||||||
|
from datetime import datetime
|
||||||
|
import time
|
||||||
|
import nhentai_manager # Import the nhentai_manager module with core functionality
|
||||||
|
|
||||||
|
# Set up dark mode
|
||||||
|
ui.dark_mode().enable()
|
||||||
|
|
||||||
|
# Global reference to UI components
|
||||||
|
history_container = None
|
||||||
|
id_input = None
|
||||||
|
app.storage.status_changed = False
|
||||||
|
|
||||||
|
def add_nhentai_id():
|
||||||
|
"""Handle adding a new nhentai ID for download"""
|
||||||
|
id_value = id_input.value
|
||||||
|
if not id_value:
|
||||||
|
ui.notify('Please enter an ID', color='warning')
|
||||||
|
return
|
||||||
|
|
||||||
|
# Clear the input field after submission
|
||||||
|
id_input.value = ''
|
||||||
|
|
||||||
|
# Add to database
|
||||||
|
nhentai_manager.db_add_download(id_value)
|
||||||
|
|
||||||
|
# Show notification
|
||||||
|
ui.notify(f'Adding nhentai ID: {id_value}')
|
||||||
|
|
||||||
|
# Refresh the download history display
|
||||||
|
refresh_download_history()
|
||||||
|
|
||||||
|
def update_status_icon(status_icon, status, message=None):
|
||||||
|
"""Update the status icon based on download status"""
|
||||||
|
if status == "pending":
|
||||||
|
status_icon.name = 'circle'
|
||||||
|
status_icon.classes('text-yellow-500', remove='text-green-500 text-red-500 text-blue-500')
|
||||||
|
elif status == "downloading":
|
||||||
|
status_icon.name = 'downloading'
|
||||||
|
status_icon.classes('text-blue-500', remove='text-yellow-500 text-green-500 text-red-500')
|
||||||
|
elif status == "success":
|
||||||
|
status_icon.name = 'check_circle'
|
||||||
|
status_icon.classes('text-green-500', remove='text-yellow-500 text-red-500 text-blue-500')
|
||||||
|
ui.notify(f'Download completed successfully', color='positive')
|
||||||
|
elif status == "error":
|
||||||
|
status_icon.name = 'error'
|
||||||
|
status_icon.classes('text-red-500', remove='text-yellow-500 text-green-500 text-blue-500')
|
||||||
|
if message:
|
||||||
|
ui.notify(f'Download failed: {message}', color='negative')
|
||||||
|
else:
|
||||||
|
ui.notify(f'Download failed', color='negative')
|
||||||
|
|
||||||
|
def safely_refresh_history():
|
||||||
|
if app.storage.status_changed:
|
||||||
|
refresh_download_history()
|
||||||
|
app.storage.status_changed = False
|
||||||
|
|
||||||
|
def on_status_change(nhentai_id, status, message=None):
|
||||||
|
"""Callback for status changes during download"""
|
||||||
|
# We need to refresh the UI to reflect the changes
|
||||||
|
app.storage.status_changed = True
|
||||||
|
|
||||||
|
def start_download(nhentai_id, status_icon):
|
||||||
|
"""Start downloading a doujinshi"""
|
||||||
|
# Update the UI status
|
||||||
|
update_status_icon(status_icon, "downloading")
|
||||||
|
ui.notify(f'Starting download for ID: {nhentai_id}', color='info')
|
||||||
|
|
||||||
|
# Start the download in a background thread
|
||||||
|
nhentai_manager.start_download_thread(nhentai_id, on_status_change)
|
||||||
|
|
||||||
|
# Set up periodic UI refresh to check for status updates
|
||||||
|
refresh_status_periodically(nhentai_id, status_icon)
|
||||||
|
|
||||||
|
def refresh_status_periodically(nhentai_id, status_icon):
|
||||||
|
"""Periodically check the download status and update the UI"""
|
||||||
|
# Get current status from database
|
||||||
|
status_info = nhentai_manager.db_get_download_status(nhentai_id)
|
||||||
|
|
||||||
|
if status_info:
|
||||||
|
status = status_info['status']
|
||||||
|
message = status_info['message']
|
||||||
|
|
||||||
|
# Update the UI based on the status
|
||||||
|
update_status_icon(status_icon, status, message)
|
||||||
|
|
||||||
|
# If still downloading, check again in a second
|
||||||
|
if status == "downloading":
|
||||||
|
ui.timer(1.0, lambda: refresh_status_periodically(nhentai_id, status_icon), once=True)
|
||||||
|
else:
|
||||||
|
# If no status found, check again in a second
|
||||||
|
ui.timer(1.0, lambda: refresh_status_periodically(nhentai_id, status_icon), once=True)
|
||||||
|
|
||||||
|
def refresh_download_history():
|
||||||
|
"""Refresh the download history display from the database"""
|
||||||
|
# Clear current history
|
||||||
|
history_container.clear()
|
||||||
|
|
||||||
|
# Get all downloads from database
|
||||||
|
downloads = nhentai_manager.db_get_all_downloads()
|
||||||
|
|
||||||
|
if not downloads:
|
||||||
|
with history_container:
|
||||||
|
ui.label('No download history yet').classes('text-gray-500 italic')
|
||||||
|
return
|
||||||
|
|
||||||
|
# Populate with data from database
|
||||||
|
for download in downloads:
|
||||||
|
nhentai_id = download['nhentai_id']
|
||||||
|
status = download['status']
|
||||||
|
added_time = datetime.fromisoformat(download['added_time']).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
with history_container:
|
||||||
|
item_row = ui.row().classes('w-full items-center')
|
||||||
|
with item_row:
|
||||||
|
# Set icon based on status
|
||||||
|
if status == 'pending':
|
||||||
|
status_icon = ui.icon('circle').classes('text-yellow-500')
|
||||||
|
elif status == 'downloading':
|
||||||
|
status_icon = ui.icon('downloading').classes('text-blue-500')
|
||||||
|
elif status == 'success':
|
||||||
|
status_icon = ui.icon('check_circle').classes('text-green-500')
|
||||||
|
elif status == 'error':
|
||||||
|
status_icon = ui.icon('error').classes('text-red-500')
|
||||||
|
else:
|
||||||
|
status_icon = ui.icon('help').classes('text-gray-500')
|
||||||
|
|
||||||
|
ui.label(f'ID: {nhentai_id}').classes('text-lg ml-2')
|
||||||
|
ui.label(f'Added: {added_time}').classes('text-sm text-gray-500 ml-auto')
|
||||||
|
|
||||||
|
# Only show download button for pending or failed downloads
|
||||||
|
if status in ['pending', 'error']:
|
||||||
|
download_btn = ui.button('Download',
|
||||||
|
on_click=lambda id=nhentai_id, icon=status_icon: start_download(id, icon),
|
||||||
|
color='primary').classes('ml-2').props('size=sm')
|
||||||
|
|
||||||
|
def show_settings():
|
||||||
|
"""Display settings dialog"""
|
||||||
|
current_settings = nhentai_manager.get_settings()
|
||||||
|
|
||||||
|
with ui.dialog() as dialog, ui.card().classes('w-96'):
|
||||||
|
ui.label('Download Settings').classes('text-xl font-bold')
|
||||||
|
|
||||||
|
# Basic Settings
|
||||||
|
ui.label('Basic Settings').classes('text-lg font-semibold mt-4')
|
||||||
|
download_dir_input = ui.input('Download Directory', value=current_settings['download_dir']).classes('w-full')
|
||||||
|
output_format_input = ui.input('Output Format', value=current_settings['output_format'],
|
||||||
|
placeholder='e.g. [%i]%s').classes('w-full')
|
||||||
|
ui.label('Supported: %i (ID), %s (subtitle), %t (title), %a (authors), %g (groups), %p (pretty name)').classes('text-xs text-gray-500')
|
||||||
|
|
||||||
|
# Advanced Settings
|
||||||
|
ui.label('Advanced Settings').classes('text-lg font-semibold mt-4')
|
||||||
|
thread_count_input = ui.number('Thread Count', value=current_settings['thread_count'], min=1, max=20)
|
||||||
|
timeout_input = ui.number('Timeout (seconds)', value=current_settings['timeout'], min=5, max=120)
|
||||||
|
retry_count_input = ui.number('Retry Count', value=current_settings['retry_count'], min=0, max=10)
|
||||||
|
|
||||||
|
# Output Options
|
||||||
|
ui.label('Output Options').classes('text-lg font-semibold mt-4')
|
||||||
|
html_viewer_toggle = ui.switch('Generate HTML Viewer', value=current_settings['html_viewer'])
|
||||||
|
cbz_toggle = ui.switch('Generate CBZ File', value=current_settings['generate_cbz'])
|
||||||
|
pdf_toggle = ui.switch('Generate PDF File', value=current_settings['generate_pdf'])
|
||||||
|
|
||||||
|
# Authentication (for bypassing Cloudflare)
|
||||||
|
ui.label('Authentication (to bypass Cloudflare)').classes('text-lg font-semibold mt-4')
|
||||||
|
cookie_input = ui.input('Cookie', value=current_settings['cookie'],
|
||||||
|
placeholder='csrftoken=TOKEN; sessionid=ID; cf_clearance=CLOUDFLARE').classes('w-full')
|
||||||
|
useragent_input = ui.input('User Agent', value=current_settings['user_agent'],
|
||||||
|
placeholder='Mozilla/5.0 ...').classes('w-full')
|
||||||
|
|
||||||
|
with ui.row():
|
||||||
|
ui.button('Cancel', on_click=dialog.close).props('outline')
|
||||||
|
ui.button('Save', on_click=lambda: save_settings(
|
||||||
|
download_dir_input.value,
|
||||||
|
output_format_input.value,
|
||||||
|
cookie_input.value,
|
||||||
|
useragent_input.value,
|
||||||
|
html_viewer_toggle.value,
|
||||||
|
cbz_toggle.value,
|
||||||
|
pdf_toggle.value,
|
||||||
|
thread_count_input.value,
|
||||||
|
timeout_input.value,
|
||||||
|
retry_count_input.value,
|
||||||
|
dialog
|
||||||
|
))
|
||||||
|
dialog.open()
|
||||||
|
|
||||||
|
def save_settings(download_dir, output_format, cookie, useragent,
|
||||||
|
html_viewer, generate_cbz, generate_pdf, thread_count, timeout, retry_count, dialog):
|
||||||
|
"""Save settings to the nhentai_manager module"""
|
||||||
|
# Update settings
|
||||||
|
new_settings = {
|
||||||
|
"download_dir": download_dir,
|
||||||
|
"output_format": output_format,
|
||||||
|
"cookie": cookie,
|
||||||
|
"user_agent": useragent,
|
||||||
|
"html_viewer": html_viewer,
|
||||||
|
"generate_cbz": generate_cbz,
|
||||||
|
"generate_pdf": generate_pdf,
|
||||||
|
"thread_count": thread_count,
|
||||||
|
"timeout": timeout,
|
||||||
|
"retry_count": retry_count
|
||||||
|
}
|
||||||
|
nhentai_manager.update_settings(new_settings)
|
||||||
|
|
||||||
|
ui.notify('Settings saved', color='positive')
|
||||||
|
dialog.close()
|
||||||
|
|
||||||
|
def setup_ui():
|
||||||
|
"""Set up the main UI components"""
|
||||||
|
global history_container, id_input
|
||||||
|
|
||||||
|
with ui.header().classes('bg-primary'):
|
||||||
|
ui.label('nhentai Downloader').classes('text-xl font-bold')
|
||||||
|
ui.space()
|
||||||
|
ui.button('Settings', on_click=show_settings).props('icon=settings flat')
|
||||||
|
|
||||||
|
# Input and button row
|
||||||
|
with ui.row().classes('w-full items-center mt-4'):
|
||||||
|
id_input = ui.input(label='ID:').classes('mr-2')
|
||||||
|
ui.button('Add ID!', on_click=add_nhentai_id).props('icon=add')
|
||||||
|
|
||||||
|
# History section
|
||||||
|
ui.label('History').classes('text-xl font-bold mt-4 mb-2')
|
||||||
|
history_container = ui.column().classes('w-full border rounded-lg p-2')
|
||||||
|
|
||||||
|
# Add some instructions initially
|
||||||
|
with history_container:
|
||||||
|
ui.label('Enter an ID and click "Add ID!" to see the history').classes('text-gray-500 italic')
|
||||||
|
|
||||||
|
# Add footer with help info
|
||||||
|
with ui.footer().classes('bg-gray-100 dark:bg-gray-800 text-sm'):
|
||||||
|
ui.label('Using nhentai CLI tool. Need help? Check the GitHub page:')
|
||||||
|
ui.link('https://github.com/RicterZ/nhentai', 'https://github.com/RicterZ/nhentai').classes('ml-1')
|
||||||
|
|
||||||
|
# Add a periodic timer to safely refresh the UI
|
||||||
|
ui.timer(1.0, safely_refresh_history)
|
||||||
|
|
||||||
|
# Initialize UI and load existing downloads on startup
|
||||||
|
@app.on_startup
|
||||||
|
def on_startup():
|
||||||
|
refresh_download_history()
|
||||||
|
|
||||||
|
if __name__ in {"__main__", "__mp_main__"}:
|
||||||
|
setup_ui()
|
||||||
|
ui.run()
|
259
src/nhentai_manager.py
Normal file
259
src/nhentai_manager.py
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
from statistics import stdev
|
||||||
|
import sqlite3
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import threading
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
DOWNLOAD_DIR = os.path.expanduser("out")
|
||||||
|
OUTPUT_FORMAT = "[%i]%s" # Default format for folder naming
|
||||||
|
COOKIE = "session-affinity=1742247176.302.46.898572|2968378f2272707dac237fc5e1f12aaf; csrftoken=UPArZ6krsCd44PZK5zut7f8tQfb7HqVH; sessionid=qszf9bsjr5kxlm9t9avhx8ivogoa4q44" # For bypassing Cloudflare captcha
|
||||||
|
USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0" # For bypassing Cloudflare captcha
|
||||||
|
HTML_VIEWER = False # Generate HTML viewer
|
||||||
|
GENERATE_CBZ = True # Generate Comic Book Archive
|
||||||
|
GENERATE_PDF = False # Generate PDF file
|
||||||
|
THREAD_COUNT = 1 # Thread count for downloading
|
||||||
|
TIMEOUT = 30 # Timeout in seconds
|
||||||
|
RETRY_COUNT = 3 # Retry times when download fails
|
||||||
|
|
||||||
|
# Database setup
|
||||||
|
def init_database():
|
||||||
|
conn = sqlite3.connect('nhentai_downloads.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Create downloads table if it doesn't exist
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS downloads (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
nhentai_id TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL,
|
||||||
|
message TEXT,
|
||||||
|
added_time TIMESTAMP NOT NULL,
|
||||||
|
updated_time TIMESTAMP NOT NULL
|
||||||
|
)
|
||||||
|
''')
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def db_add_download(nhentai_id):
|
||||||
|
conn = sqlite3.connect('nhentai_downloads.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
now = datetime.now().isoformat()
|
||||||
|
cursor.execute(
|
||||||
|
"INSERT INTO downloads (nhentai_id, status, added_time, updated_time) VALUES (?, ?, ?, ?)",
|
||||||
|
(nhentai_id, "pending", now, now)
|
||||||
|
)
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def db_update_download_status(nhentai_id, status, message=None):
|
||||||
|
conn = sqlite3.connect('nhentai_downloads.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
now = datetime.now().isoformat()
|
||||||
|
cursor.execute(
|
||||||
|
"UPDATE downloads SET status = ?, message = ?, updated_time = ? WHERE nhentai_id = ?",
|
||||||
|
(status, message, now, nhentai_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def db_get_all_downloads():
|
||||||
|
conn = sqlite3.connect('nhentai_downloads.db')
|
||||||
|
conn.row_factory = sqlite3.Row # This enables column access by name
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute("SELECT * FROM downloads ORDER BY added_time DESC")
|
||||||
|
downloads = [dict(row) for row in cursor.fetchall()]
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
return downloads
|
||||||
|
|
||||||
|
def db_get_download_status(nhentai_id):
|
||||||
|
conn = sqlite3.connect('nhentai_downloads.db')
|
||||||
|
conn.row_factory = sqlite3.Row
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute("SELECT status, message FROM downloads WHERE nhentai_id = ?", (nhentai_id,))
|
||||||
|
result = cursor.fetchone()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if result:
|
||||||
|
return {'status': result['status'], 'message': result['message']}
|
||||||
|
return None
|
||||||
|
|
||||||
|
def download_doujinshi(nhentai_id, on_status_change=None):
|
||||||
|
"""
|
||||||
|
Download a doujinshi using nhentai CLI.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nhentai_id: The ID to download
|
||||||
|
on_status_change: Optional callback for status updates
|
||||||
|
"""
|
||||||
|
# Update status in the database
|
||||||
|
db_update_download_status(nhentai_id, "downloading")
|
||||||
|
if on_status_change:
|
||||||
|
on_status_change(nhentai_id, "downloading")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Try to check if nhentai CLI is installed
|
||||||
|
try:
|
||||||
|
subprocess.run(["nhentai", "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
|
||||||
|
except (subprocess.SubprocessError, FileNotFoundError):
|
||||||
|
error_msg = "nhentai CLI tool is not installed"
|
||||||
|
db_update_download_status(nhentai_id, "error", error_msg)
|
||||||
|
if on_status_change:
|
||||||
|
on_status_change(nhentai_id, "error", error_msg)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Create download directory if it doesn't exist
|
||||||
|
os.makedirs(DOWNLOAD_DIR, exist_ok=True)
|
||||||
|
|
||||||
|
# Build command with all options
|
||||||
|
cmd = ["nhentai"]
|
||||||
|
|
||||||
|
# Add the ID
|
||||||
|
cmd.extend(["--id", str(nhentai_id)])
|
||||||
|
|
||||||
|
# Add explicit download flag to make sure it downloads
|
||||||
|
cmd.append("--download")
|
||||||
|
|
||||||
|
# Add output directory
|
||||||
|
cmd.extend(["--output", DOWNLOAD_DIR])
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
cmd.extend(["--move-to-folder"])
|
||||||
|
|
||||||
|
# Add format option
|
||||||
|
cmd.extend(["--format", f"'{OUTPUT_FORMAT}'"])
|
||||||
|
|
||||||
|
# Add thread count
|
||||||
|
if THREAD_COUNT > 0:
|
||||||
|
cmd.extend(["--threads", str(THREAD_COUNT)])
|
||||||
|
|
||||||
|
# Add timeout
|
||||||
|
if TIMEOUT > 0:
|
||||||
|
cmd.extend(["--timeout", str(TIMEOUT)])
|
||||||
|
|
||||||
|
# Add retry count
|
||||||
|
if RETRY_COUNT > 0:
|
||||||
|
cmd.extend(["--retry", str(RETRY_COUNT)])
|
||||||
|
|
||||||
|
# Add exit-on-fail option to prevent incomplete downloads
|
||||||
|
cmd.append("--exit-on-fail")
|
||||||
|
|
||||||
|
# Add HTML viewer option
|
||||||
|
if HTML_VIEWER:
|
||||||
|
cmd.append("--html")
|
||||||
|
else:
|
||||||
|
cmd.append("--no-html")
|
||||||
|
|
||||||
|
# Generate CBZ if selected
|
||||||
|
if GENERATE_CBZ:
|
||||||
|
cmd.append("--cbz")
|
||||||
|
|
||||||
|
# Generate PDF if selected
|
||||||
|
if GENERATE_PDF:
|
||||||
|
cmd.append("--pdf")
|
||||||
|
|
||||||
|
# Add cookie if provided
|
||||||
|
if COOKIE:
|
||||||
|
subprocess.run(["nhentai", f"--cookie=\"{COOKIE}\""],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
print("Set nhentai cookie")
|
||||||
|
|
||||||
|
# Add user agent if provided
|
||||||
|
if USER_AGENT:
|
||||||
|
subprocess.run(["nhentai", f"--useragent=\"{USER_AGENT}\""],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
print("Set nhentai user agent")
|
||||||
|
|
||||||
|
# For debugging: print the command (excluding sensitive info)
|
||||||
|
debug_cmd = list(cmd)
|
||||||
|
|
||||||
|
print(f"Executing: {' '.join(debug_cmd)}")
|
||||||
|
print(f"Working directory: {os.getcwd()}")
|
||||||
|
print(f"Download directory: {DOWNLOAD_DIR}")
|
||||||
|
|
||||||
|
process = subprocess.Popen(
|
||||||
|
cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
text=True
|
||||||
|
)
|
||||||
|
stdout, stderr = process.communicate()
|
||||||
|
print(f"Full STDOUT: {stdout}")
|
||||||
|
if (stderr):
|
||||||
|
print(f"Full STDERR: {stderr}")
|
||||||
|
|
||||||
|
if process.returncode == 0:
|
||||||
|
# Success
|
||||||
|
db_update_download_status(nhentai_id, "success", "Download completed")
|
||||||
|
if on_status_change:
|
||||||
|
on_status_change(nhentai_id, "success", "Download completed")
|
||||||
|
print(f"Download successful for ID {nhentai_id}")
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Error
|
||||||
|
error_msg = f'Download failed: {stderr}'
|
||||||
|
db_update_download_status(nhentai_id, "error", error_msg)
|
||||||
|
if on_status_change:
|
||||||
|
on_status_change(nhentai_id, "error", error_msg)
|
||||||
|
print(f"Download failed for ID {nhentai_id}")
|
||||||
|
print(f"STDERR: {stderr}")
|
||||||
|
except Exception as e:
|
||||||
|
# Error handling
|
||||||
|
error_msg = f'Error: {str(e)}'
|
||||||
|
db_update_download_status(nhentai_id, "error", error_msg)
|
||||||
|
if on_status_change:
|
||||||
|
on_status_change(nhentai_id, "error", error_msg)
|
||||||
|
print(f"Exception during download for ID {nhentai_id}: {str(e)}")
|
||||||
|
|
||||||
|
def start_download_thread(nhentai_id, on_status_change=None):
|
||||||
|
"""Starts a download in a background thread"""
|
||||||
|
threading.Thread(
|
||||||
|
target=download_doujinshi,
|
||||||
|
args=(nhentai_id, on_status_change),
|
||||||
|
daemon=True
|
||||||
|
).start()
|
||||||
|
|
||||||
|
def get_settings():
|
||||||
|
"""Return current settings as a dict"""
|
||||||
|
return {
|
||||||
|
"download_dir": DOWNLOAD_DIR,
|
||||||
|
"output_format": OUTPUT_FORMAT,
|
||||||
|
"cookie": COOKIE,
|
||||||
|
"user_agent": USER_AGENT,
|
||||||
|
"html_viewer": HTML_VIEWER,
|
||||||
|
"generate_cbz": GENERATE_CBZ,
|
||||||
|
"generate_pdf": GENERATE_PDF,
|
||||||
|
"thread_count": THREAD_COUNT,
|
||||||
|
"timeout": TIMEOUT,
|
||||||
|
"retry_count": RETRY_COUNT
|
||||||
|
}
|
||||||
|
|
||||||
|
def update_settings(settings):
|
||||||
|
"""Update global settings from a dict"""
|
||||||
|
global DOWNLOAD_DIR, OUTPUT_FORMAT, COOKIE, USER_AGENT, HTML_VIEWER
|
||||||
|
global GENERATE_CBZ, GENERATE_PDF, THREAD_COUNT, TIMEOUT, RETRY_COUNT
|
||||||
|
|
||||||
|
DOWNLOAD_DIR = settings.get("download_dir", DOWNLOAD_DIR)
|
||||||
|
OUTPUT_FORMAT = settings.get("output_format", OUTPUT_FORMAT)
|
||||||
|
COOKIE = settings.get("cookie", COOKIE)
|
||||||
|
USER_AGENT = settings.get("user_agent", USER_AGENT)
|
||||||
|
HTML_VIEWER = settings.get("html_viewer", HTML_VIEWER)
|
||||||
|
GENERATE_CBZ = settings.get("generate_cbz", GENERATE_CBZ)
|
||||||
|
GENERATE_PDF = settings.get("generate_pdf", GENERATE_PDF)
|
||||||
|
THREAD_COUNT = settings.get("thread_count", THREAD_COUNT)
|
||||||
|
TIMEOUT = settings.get("timeout", TIMEOUT)
|
||||||
|
RETRY_COUNT = settings.get("retry_count", RETRY_COUNT)
|
||||||
|
|
||||||
|
# Initialize database when module is imported
|
||||||
|
init_database()
|
Loading…
x
Reference in New Issue
Block a user