-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcli.py
194 lines (162 loc) · 5.91 KB
/
cli.py
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
import os
import sys
import time
import pendulum
import tomlkit as toml
import typer
from dict_deep import deep_set
from path import Path
from rich import print
from labosphere import callbacks, utils
from labosphere.constants import BASE_URL, DOCKER, GITHUB_ACTIONS, LABOSPHERE_DIR
app = typer.Typer(no_args_is_help=True)
@app.command("start")
def start(
start_from: float = typer.Option(
None, "--from", help="The number of the newest chapter to retrieve."
),
end_at: float = typer.Option(
1, "--to", min=1, help="The number of the oldest chapter to retrieve."
),
explicit_chapters: list[float] = typer.Option(
...,
"--chapter",
"-c",
default_factory=list,
help="The number of a specific chapter to retrieve. Specify multiple times "
"for multiple chapters. If specified, only chapters provided to "
"this option will be retrieved. "
"Overrides --from and --to.",
show_default=False,
),
cooldown: int = typer.Option(
0,
min=0,
help="The number of seconds to wait between sending requests to TCB Scans.",
),
timeout: int = typer.Option(
None,
min=0,
help="Labosphere will exit after requesting this many consecutive chapters "
"with no changes.",
),
):
"""
Run Labosphere.
"""
chapter_pool = utils.get_chapter_list()
latest_chapter = float(utils.get_chapter_number(chapter_pool[0]))
start_from = start_from or latest_chapter
viz_titles = toml.load((LABOSPHERE_DIR / "titles.toml").open())
volumes = toml.load((LABOSPHERE_DIR / "volumes.toml").open())
if start_from > latest_chapter:
raise typer.BadParameter(
f"{utils.truncate(start_from)} is greater than the latest chapter number "
f"({utils.truncate(latest_chapter)}).",
param_hint="--from",
)
elif start_from < end_at:
raise typer.BadParameter(
f"--from ({utils.truncate(start_from)}) is less than --to ({utils.truncate(end_at)})."
)
if explicit_chapters:
chapter_pool = [
c for c in chapter_pool if utils.get_chapter_number(c) in explicit_chapters
]
else:
chapter_pool = [
c
for c in chapter_pool
if start_from >= utils.get_chapter_number(c) >= end_at
]
updated_chapters = 0
timeout_tracker = 0
for chapter in chapter_pool:
chapter_number = utils.get_chapter_number(chapter)
if explicit_chapters and chapter_number not in explicit_chapters:
continue
cubari = utils.load_cubari()
cubari["chapters"] = cubari.get("chapters", {})
chapter_title = (
chapter.text.splitlines()[2].strip()
or viz_titles.get(str(utils.truncate(chapter_number)))
or "TBD" # This last fallback should *never* actually be reached in practice, but better safe than sorry.
)
translation_group = "VIZ Media" if chapter_number < 999 else "TCB Scans"
soup = utils.get_soup(BASE_URL / chapter.get("href").lstrip("/"))
pages = soup.find_all(
"img", src=lambda src: src and "cdn.onepiecechapters.com" in src
)
old_metadata = utils.deep_get(
cubari, f"chapters|{utils.truncate(chapter_number)}", default={}, sep="|"
)
new_metadata = {
"title": chapter_title,
"groups": {
translation_group: [
page.get("src") for page in pages if page.parent.name != "a"
]
},
}
# The volume number, if one exists, is the first key in volumes.toml for which the value is
# greater than or equal to the chapter number.
chapter_volume = next(
(vol for vol, bound in volumes.items() if bound >= chapter_number), None
)
if chapter_volume:
new_metadata["volume"] = chapter_volume
if utils.without_keys(old_metadata, "last_updated") != new_metadata:
timeout_tracker = 0
deep_set(
cubari,
f"chapters|{utils.truncate(chapter_number)}",
{
**new_metadata,
"last_updated": int(pendulum.now("UTC").timestamp()),
},
sep="|",
)
utils.dump_cubari(cubari)
print(
f"Updated Chapter {utils.truncate(chapter_number)}: {chapter_title}"
if chapter_title
else f"Updated Chapter {utils.truncate(chapter_number)}"
)
else:
updated_chapters += 1
timeout_tracker += 1
print(
f"No changes to Chapter {utils.truncate(chapter_number)}: {chapter_title}"
if chapter_title
else f"No changes to Chapter {utils.truncate(chapter_number)}"
)
if timeout and timeout_tracker >= timeout:
print(f"Requested {timeout} consecutive chapters with no changes. Exiting.")
sys.exit()
time.sleep(cooldown)
if timeout and updated_chapters >= timeout and GITHUB_ACTIONS:
print("LABOSPHERE_FLAG_PR=1", file=open(os.getenv("GITHUB_ENV"), "a"))
if DOCKER:
mount = Path("/labosphere")
mount.mkdir_p()
(mount / "cubari.json").write_text(utils.cubari_path().read_text())
exit()
# noinspection PyUnusedLocal
@app.callback(
epilog=f"Labosphere © {pendulum.now().year} celsius narhwal. Thank you kindly for your attention."
)
def main(
license: bool = typer.Option(
None,
"--license",
is_eager=True,
help="View Labosphere's license.",
callback=callbacks.license,
rich_help_panel="About Labosphere",
),
):
"""
Labosphere generates Cubari repositories for TCB Scans' One Piece releases.
"""
if __name__ == "__main__":
app()