-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.py
157 lines (120 loc) · 4.41 KB
/
main.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
import asyncio
import logging
import pathlib
import aiofiles.os
import aiofiles
import httpx
from tqdm.asyncio import tqdm
from InquirerPy import inquirer
from InquirerPy.validator import EmptyInputValidator
from politodown import session, get_material, get_videostores
from politodown.http import LoginError
from politodown.datatypes import Assignment, Folder, FileNotFound, get_valid_filename, get_relative_path
def retryonfail(func, generator: bool = False):
async def letstry(*args, **kwargs):
try:
await func(*args, **kwargs)
except (httpx.ConnectTimeout, httpx.ConnectError, httpx.RemoteProtocolError, httpx.HTTPStatusError) as e:
logging.warning(e)
await asyncio.sleep(5)
await letstry(*args, **kwargs)
except Exception as e:
logging.error(e)
raise
return letstry
class postfix:
def __init__(self, string: str):
self.string = string
def __str__(self) -> str:
return self.string
@retryonfail
async def download(inc, basepath: pathlib.Path):
bar_format = "{l_bar}{bar}| {n_fmt}/{total_fmt} [{postfix}]"
if isinstance(inc, Assignment):
filecount = 0
async for _ in inc.files(True):
filecount += 1
pbar = tqdm(inc.files(True), total=filecount, position=0, bar_format=bar_format)
else:
pbar = tqdm((await inc.videolessons()).values(), total=len(await inc.videolessons()), position=0, bar_format=bar_format)
async for file in pbar:
path = basepath/get_relative_path(file)
await aiofiles.os.makedirs(path.parent, exist_ok=True)
if path.parent.stem != get_valid_filename(inc.name):
pbar.postfix = postfix(path.parent.stem)
with tqdm(total=1, position=1, leave=False, unit='B',
unit_scale=True, unit_divisor=1024,
postfix={"file": file.name[-10:]}) as dbar:
try:
async for chunk_length in file.save(path.parent, lambda file: file.name if isinstance(file.parent, Folder) else file.filename):
if chunk_length == -1:
logging.info("%s skipped", path)
continue
dbar.total = file.size
dbar.update(chunk_length)
except FileNotFound:
logging.warning("%s not found", path)
async def login(username: str, password: str) -> bool:
await session.signin(username, password)
async def main():
username = await inquirer.text(message="Username:").execute_async()
password = await inquirer.secret(
message="Password:",
transformer=lambda _: "[hidden]",
).execute_async()
try:
await login(username, password)
except LoginError as e:
await inquirer.text(
f"Login error: {e}",
instruction="Press enter to continue.",
mandatory=False,
).execute_async()
return await main()
await home()
async def home():
choosetype = await inquirer.select(
message="Choose type:",
choices=[
"Materiali",
"Videolezioni",
],
).execute_async()
year = await inquirer.number(
message="Year:",
min_allowed=2002,
max_allowed=2023,
default=2023,
validate=EmptyInputValidator(),
).execute_async()
year = int(year)
if choosetype == "Materiali":
await choose_material(await get_material(year))
else:
await videostores(await get_videostores(year))
async def choose_material(mat):
answer = await inquirer.fuzzy(
message="Choose material:",
choices=mat.keys(),
).execute_async()
material = mat[answer]
_assignments = await material.assignments()
await assignments(_assignments)
async def assignments(assignments):
answer = await inquirer.fuzzy(
message="Choose assignments:",
choices=assignments.keys(),
).execute_async()
inc = assignments[answer]
await download(inc, pathlib.Path("Materiali"))
async def videostores(vid):
videostore = await inquirer.select(
message="Choose videostore collection:",
choices=vid.keys(),
).execute_async()
answer = await inquirer.fuzzy(
message="Choose videostore:",
choices=vid[videostore].keys(),
).execute_async()
await download(vid[videostore][answer], pathlib.Path("Videolezioni"))
asyncio.run(main())