Repository navigation
Expand file tree
/
Copy pathConvertBooks.py
More file actions
115 lines (91 loc) · 4.49 KB
/
Copy pathConvertBooks.py
File metadata and controls
115 lines (91 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import os
import shutil
import subprocess
from time import sleep
from datetime import datetime
import logging
import concurrent.futures
def convert_book(input_file, output_file):
try:
subprocess.run(["ebook-convert", input_file, output_file], check=True)
logging.info(f"Converted {input_file} to {output_file}")
except subprocess.CalledProcessError as e:
logging.error(f"Error converting {input_file}: {e}")
except Exception as e:
logging.error(f"Error converting {input_file}: {str(e)}")
def copy_book(input_file, output_file):
try:
shutil.copy(input_file, output_file)
logging.info(f"Copied {input_file} to {output_file}")
except Exception as e:
logging.error(f"Error copying {input_file}: {str(e)}")
def delete_book(input_file):
try:
os.remove(input_file)
logging.info(f"Deleted source file: {input_file}")
except Exception as e:
logging.error(f"Couldn't delete {input_file}\nError: {str(e)}")
def run_conversion():
with concurrent.futures.ThreadPoolExecutor(max_workers=thread_limit) as executor:
futures = []
for root, dirs, files in os.walk(source_folder):
if not dirs and not files:
logging.error(f"The directory {source_folder} is empty.")
return
book_files = [file for file in files if any(file.endswith(format) for format in book_source_formats)]
unique_books = set([os.path.splitext(book)[0] for book in book_files])
format_count = len(desired_output_formats)
for book in unique_books:
for source_format in book_source_formats:
book_path = os.path.join(root, f"{book}{source_format}")
if os.path.exists(book_path):
input_file = book_path
break
else:
logging.warning(f"No valid input file found for {book}")
continue
format_index = 1
for output_format in desired_output_formats:
relative_root = os.path.relpath(root, source_folder)
output_file_dir = os.path.join(destination_folder, relative_root)
if not os.path.exists(output_file_dir):
os.makedirs(output_file_dir, exist_ok=True)
output_file = os.path.join(output_file_dir, f"{book}{output_format}")
if not os.path.exists(output_file):
if source_format == output_format:
futures.append(executor.submit(copy_book, input_file, output_file))
else:
futures.append(executor.submit(convert_book, input_file, output_file))
if delete_source_when_done.lower() == "true" and format_index == format_count:
futures.append(executor.submit(delete_book, input_file))
format_index += 1
concurrent.futures.wait(futures)
logging.info(f"Conversion Complete, sleeping...")
logging.basicConfig(level=logging.INFO, format="%(levelname)s - %(message)s")
app_name_text = os.path.basename(__file__).replace(".py", "")
release_version = os.environ.get("RELEASE_VERSION", "unknown")
logging.info(f"{'*' * 50}\n")
logging.info(f"{app_name_text} Version: {release_version}\n")
logging.info(f"{'*' * 50}")
book_source_formats = os.getenv("book_source_formats", ".epub,.mobi,.azw3").split(",")
desired_output_formats = os.getenv("desired_output_formats", ".mobi,.azw3").split(",")
schedule = os.getenv("schedule", "0").split(",")
schedule = [int(hour.strip()) for hour in schedule]
run_at_startup = os.getenv("run_at_startup", "false")
thread_limit = int(os.getenv("thread_limit", 1))
delete_source_when_done = os.getenv("delete_source_when_done", "false")
source_folder = "source"
if not os.path.exists(source_folder):
os.makedirs(source_folder, exist_ok=True)
destination_folder = "destination"
if not os.path.exists(destination_folder):
os.makedirs(destination_folder, exist_ok=True)
if run_at_startup.lower() == "true":
run_conversion()
sleep(3600)
while True:
if datetime.now().hour in schedule:
run_conversion()
else:
logging.info(f"Current hour is {datetime.now().hour}. Not a scheduled run hour. Sleeping...")
sleep(3600)