rcdl 3.0.0b13__py3-none-any.whl → 3.0.0b23__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rcdl/core/downloader_subprocess.py +5 -1
- rcdl/gui/video_manager.py +35 -27
- rcdl/interface/ui.py +17 -5
- rcdl/utils.py +17 -6
- {rcdl-3.0.0b13.dist-info → rcdl-3.0.0b23.dist-info}/METADATA +1 -1
- {rcdl-3.0.0b13.dist-info → rcdl-3.0.0b23.dist-info}/RECORD +8 -8
- {rcdl-3.0.0b13.dist-info → rcdl-3.0.0b23.dist-info}/WHEEL +0 -0
- {rcdl-3.0.0b13.dist-info → rcdl-3.0.0b23.dist-info}/entry_points.txt +0 -0
|
@@ -14,6 +14,7 @@ from rcdl.interface.ui import UI, NestedProgress
|
|
|
14
14
|
from rcdl.core import parser
|
|
15
15
|
from rcdl.core.models import Media, Post
|
|
16
16
|
from rcdl.core.config import Config
|
|
17
|
+
from rcdl.utils import bytes_to_str
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
def ytdlp_clear_cache():
|
|
@@ -338,7 +339,10 @@ def handbrake_optimized(media: Media, user: str, progress: NestedProgress):
|
|
|
338
339
|
|
|
339
340
|
assert process.stdout is not None
|
|
340
341
|
progress.start_current(description="Optimizing", total=100)
|
|
341
|
-
progress.set_status(
|
|
342
|
+
progress.set_status(
|
|
343
|
+
f"{user}@({media.service}) -> ",
|
|
344
|
+
f"{media.file_path} ({bytes_to_str(media.file_size)})",
|
|
345
|
+
)
|
|
342
346
|
|
|
343
347
|
current_progress = 0.0
|
|
344
348
|
|
rcdl/gui/video_manager.py
CHANGED
|
@@ -28,62 +28,72 @@ def set_status(media: Media, status: Status):
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
def video_manager():
|
|
31
|
+
if "reload_medias" not in st.session_state:
|
|
32
|
+
st.session_state.reload_medias = True
|
|
33
|
+
|
|
31
34
|
st.title("Video Manager")
|
|
32
35
|
|
|
33
36
|
# Filter & Sorting UI
|
|
34
37
|
with st.expander("Filters & Sorting", expanded=True):
|
|
35
38
|
col1, col2, col3 = st.columns(3)
|
|
36
39
|
with col1:
|
|
37
|
-
|
|
40
|
+
st.selectbox(
|
|
38
41
|
"Sort By",
|
|
39
42
|
options=["file_size", "service", "duration", "file_path"],
|
|
40
43
|
index=0,
|
|
44
|
+
key="sort_by",
|
|
41
45
|
)
|
|
42
46
|
with col2:
|
|
43
|
-
|
|
47
|
+
st.radio(
|
|
44
48
|
"Order",
|
|
45
49
|
options=[True, False],
|
|
46
50
|
format_func=lambda x: "Ascending" if x else "Descending",
|
|
47
51
|
horizontal=True,
|
|
52
|
+
key="ascending",
|
|
48
53
|
)
|
|
49
54
|
with col3:
|
|
50
|
-
|
|
51
|
-
"Creator ID(user)",
|
|
55
|
+
st.text_input(
|
|
56
|
+
"Creator ID(user)",
|
|
57
|
+
placeholder="Leave empty for all",
|
|
58
|
+
key="creator_filter",
|
|
52
59
|
)
|
|
53
|
-
|
|
60
|
+
st.multiselect(
|
|
54
61
|
"Status",
|
|
55
62
|
options=list(Status),
|
|
56
63
|
default=[Status.DOWNLOADED, Status.OPTIMIZED],
|
|
64
|
+
key="status_filter",
|
|
57
65
|
)
|
|
58
66
|
|
|
59
|
-
|
|
67
|
+
if st.button("Apply"):
|
|
68
|
+
st.session_state.reload_medias = True
|
|
60
69
|
|
|
61
70
|
# load db
|
|
62
|
-
if
|
|
71
|
+
if st.session_state.reload_medias or "medias" not in st.session_state:
|
|
63
72
|
with DB() as db:
|
|
64
73
|
medias = db.query_medias_by_status_sorted(
|
|
65
|
-
status_filter,
|
|
66
|
-
sort_by=sort_by,
|
|
67
|
-
ascending=ascending,
|
|
74
|
+
st.session_state.status_filter,
|
|
75
|
+
sort_by=st.session_state.sort_by,
|
|
76
|
+
ascending=st.session_state.ascending,
|
|
68
77
|
)
|
|
69
78
|
|
|
70
79
|
# check if in a fuse group
|
|
71
80
|
|
|
72
81
|
# creator filter
|
|
73
|
-
if creator_filter:
|
|
82
|
+
if st.session_state.creator_filter:
|
|
74
83
|
filtered = []
|
|
75
84
|
for m in medias:
|
|
76
85
|
post = db.query_post_by_id(m.post_id)
|
|
77
|
-
if
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
86
|
+
if (
|
|
87
|
+
post
|
|
88
|
+
and post.user == st.session_state.creator_filter
|
|
89
|
+
and db.query_fuses_by_id(m.post_id) is None
|
|
90
|
+
):
|
|
82
91
|
filtered.append(m)
|
|
83
92
|
medias = filtered
|
|
84
93
|
|
|
85
94
|
st.session_state.medias = medias
|
|
86
95
|
st.session_state.media_index = 0
|
|
96
|
+
st.session_state.reload_medias = False
|
|
87
97
|
|
|
88
98
|
medias = st.session_state.medias
|
|
89
99
|
if not medias:
|
|
@@ -157,14 +167,12 @@ def video_manager():
|
|
|
157
167
|
st.rerun()
|
|
158
168
|
|
|
159
169
|
# video player
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
else:
|
|
170
|
-
st.error(f"Video file {full_path} not found on disk")
|
|
170
|
+
with col_video:
|
|
171
|
+
full_path = os.path.join(Config.creator_folder(post.user), media.file_path)
|
|
172
|
+
video_slot = st.empty()
|
|
173
|
+
video_slot.empty()
|
|
174
|
+
|
|
175
|
+
if os.path.exists(full_path):
|
|
176
|
+
video_slot.video(full_path, autoplay=False, loop=False)
|
|
177
|
+
else:
|
|
178
|
+
st.error(f"Video file {full_path} not found on disk")
|
rcdl/interface/ui.py
CHANGED
|
@@ -28,6 +28,7 @@ class NestedProgress:
|
|
|
28
28
|
self.total_task: int | None = None
|
|
29
29
|
self.current_task: int | None = None
|
|
30
30
|
self.status_text = Text("", style="cyan")
|
|
31
|
+
self.current_label = ""
|
|
31
32
|
|
|
32
33
|
def start(
|
|
33
34
|
self, *, total: int, total_label: str = "Total", current_label: str = "Current"
|
|
@@ -54,6 +55,7 @@ class NestedProgress:
|
|
|
54
55
|
transient=False,
|
|
55
56
|
)
|
|
56
57
|
|
|
58
|
+
self.current_label = current_label
|
|
57
59
|
group = Group(self.global_progress, self.current_progress, self.status_text)
|
|
58
60
|
self.live = Live(group, console=self.console)
|
|
59
61
|
self.live.__enter__()
|
|
@@ -68,14 +70,28 @@ class NestedProgress:
|
|
|
68
70
|
if self.global_progress and self.total_task is not None:
|
|
69
71
|
self.global_progress.advance(self.total_task, step) # type: ignore
|
|
70
72
|
|
|
73
|
+
def reset_current(self):
|
|
74
|
+
if not self.current_progress or self.current_task is None:
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
self.current_progress.remove_task(self.current_task) # type: ignore
|
|
78
|
+
|
|
79
|
+
self.current_task = self.current_progress.add_task(
|
|
80
|
+
self.current_label,
|
|
81
|
+
total=1,
|
|
82
|
+
visible=False,
|
|
83
|
+
)
|
|
84
|
+
|
|
71
85
|
def start_current(self, description: str, total: int | None = None):
|
|
72
86
|
if not self.current_progress or self.current_task is None:
|
|
73
87
|
return
|
|
74
88
|
|
|
89
|
+
self.reset_current()
|
|
90
|
+
|
|
75
91
|
self.current_progress.update(
|
|
76
92
|
self.current_task, # type: ignore
|
|
77
93
|
description=description,
|
|
78
|
-
total=total,
|
|
94
|
+
total=total or 1,
|
|
79
95
|
completed=0,
|
|
80
96
|
visible=True,
|
|
81
97
|
)
|
|
@@ -88,18 +104,14 @@ class NestedProgress:
|
|
|
88
104
|
if self.current_progress and self.current_task is not None:
|
|
89
105
|
self.current_progress.update(self.current_task, visible=False) # type: ignore
|
|
90
106
|
|
|
91
|
-
# ---------------------
|
|
92
107
|
# Status line
|
|
93
|
-
# ---------------------
|
|
94
108
|
def set_status(self, cyan: str, green: str = ""):
|
|
95
109
|
self.status_text.plain = ""
|
|
96
110
|
self.status_text.append(cyan, style="cyan")
|
|
97
111
|
if green:
|
|
98
112
|
self.status_text.append(green, style="green")
|
|
99
113
|
|
|
100
|
-
# ---------------------
|
|
101
114
|
# Close
|
|
102
|
-
# ---------------------
|
|
103
115
|
def close(self):
|
|
104
116
|
if self.live:
|
|
105
117
|
self.live.__exit__(None, None, None)
|
rcdl/utils.py
CHANGED
|
@@ -9,7 +9,6 @@ from pathlib import Path
|
|
|
9
9
|
import os
|
|
10
10
|
import time
|
|
11
11
|
|
|
12
|
-
import rcdl.core.downloader_subprocess as dls
|
|
13
12
|
from rcdl.core.config import Config
|
|
14
13
|
from rcdl.interface.ui import UI
|
|
15
14
|
|
|
@@ -21,6 +20,8 @@ def get_date_now() -> str:
|
|
|
21
20
|
|
|
22
21
|
def get_media_metadata(full_path: str) -> tuple[int, int, str]:
|
|
23
22
|
"""Get duration (if possible), file_size and checksum"""
|
|
23
|
+
from rcdl.core.downloader_subprocess import ffprobe_get_duration
|
|
24
|
+
|
|
24
25
|
path = Path(full_path)
|
|
25
26
|
if not os.path.exists(path):
|
|
26
27
|
UI.error(f"{path} path should exist but does not.")
|
|
@@ -29,7 +30,7 @@ def get_media_metadata(full_path: str) -> tuple[int, int, str]:
|
|
|
29
30
|
checksum = get_media_hash(path)
|
|
30
31
|
if checksum is None:
|
|
31
32
|
checksum = ""
|
|
32
|
-
duration =
|
|
33
|
+
duration = ffprobe_get_duration(path)
|
|
33
34
|
if duration is None:
|
|
34
35
|
duration = 0
|
|
35
36
|
return duration, file_size, checksum
|
|
@@ -66,8 +67,17 @@ def get_json_hash(data: dict) -> tuple[str, str]:
|
|
|
66
67
|
return raw_json, json_hash
|
|
67
68
|
|
|
68
69
|
|
|
69
|
-
def bytes_to_mb(bytes: float | int):
|
|
70
|
-
return
|
|
70
|
+
def bytes_to_mb(bytes: float | int) -> float:
|
|
71
|
+
return bytes / (1024 * 1024)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def bytes_to_str(bytes: float | int) -> str:
|
|
75
|
+
mb = bytes_to_mb(bytes)
|
|
76
|
+
|
|
77
|
+
if mb > 1024:
|
|
78
|
+
gb = mb / 1024
|
|
79
|
+
return f"{gb:.1f} GB"
|
|
80
|
+
return f"{mb:.1f} MB"
|
|
71
81
|
|
|
72
82
|
|
|
73
83
|
def clean_all(all: bool, partial: bool, cache: bool, medias_deleted: bool):
|
|
@@ -75,6 +85,7 @@ def clean_all(all: bool, partial: bool, cache: bool, medias_deleted: bool):
|
|
|
75
85
|
|
|
76
86
|
from rcdl.core.db import DB
|
|
77
87
|
from rcdl.core.models import Status
|
|
88
|
+
from rcdl.core.downloader_subprocess import ytdlp_clear_cache, kill_aria2c
|
|
78
89
|
|
|
79
90
|
if all:
|
|
80
91
|
partial = True
|
|
@@ -106,11 +117,11 @@ def clean_all(all: bool, partial: bool, cache: bool, medias_deleted: bool):
|
|
|
106
117
|
# cache
|
|
107
118
|
if cache:
|
|
108
119
|
# clear yt-dlp cache
|
|
109
|
-
|
|
120
|
+
ytdlp_clear_cache()
|
|
110
121
|
UI.info("Cleared yt-dlp cache dir")
|
|
111
122
|
|
|
112
123
|
# kill aria2c
|
|
113
|
-
|
|
124
|
+
kill_aria2c()
|
|
114
125
|
UI.info("Kill aria2c")
|
|
115
126
|
|
|
116
127
|
# medias with status deleted
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
rcdl/__init__.py,sha256=MIsNipkMNzSOT2WkNbSmVLvo3sdPBPN0xCOMP2r5z50,175
|
|
2
2
|
rcdl/__main__.py,sha256=ge7lh3rCaWuUgVpwU88zyQGPtZgG7GLW4rslT9wo9j8,714
|
|
3
|
-
rcdl/utils.py,sha256=
|
|
3
|
+
rcdl/utils.py,sha256=3WiJhtdafyEDYR4fYUBoqH6sVdSHbjghkROeJby8ScQ,5279
|
|
4
4
|
rcdl/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
rcdl/core/adapters.py,sha256=I__3dvSwI2W8ZZfao9RNzdyLivGBOVDk_zfx39KIuHc,7258
|
|
6
6
|
rcdl/core/api.py,sha256=2OAUQV89mq1ELo9Ydj9zCde5qGHgI7bom8XLSeq7Ok8,2342
|
|
@@ -8,7 +8,7 @@ rcdl/core/config.py,sha256=9b5HTKLpBWShXqpTbgQUq3xdCqDQUs466nI16fRiWEk,6315
|
|
|
8
8
|
rcdl/core/db.py,sha256=Ab6SuC093fQvJybbzYHvhYEkCdGW-BheUrpZhM-6j1A,9302
|
|
9
9
|
rcdl/core/db_queries.py,sha256=KZW3SotPZamDxPY1KcCxo9-GvgnW6vjxDFu4h3HI1m8,2225
|
|
10
10
|
rcdl/core/downloader.py,sha256=UyMz_c-kHmmASIhd8Co3khHuaTYOUTRpizp1zr-BHjY,10329
|
|
11
|
-
rcdl/core/downloader_subprocess.py,sha256=
|
|
11
|
+
rcdl/core/downloader_subprocess.py,sha256=w9WPH2pOTFv-4dEp_iklN1bZLydGd3MjTfhiQEkp7Es,10375
|
|
12
12
|
rcdl/core/file_io.py,sha256=C-W9GLQReGiuWKTLzVTsisI_ps5j0SeqNQM9VjJot14,1040
|
|
13
13
|
rcdl/core/fuse.py,sha256=OKeWHh-WXWicLeCq_jgqKQovdDPfKAk2fi8lgUV-FKw,4188
|
|
14
14
|
rcdl/core/models.py,sha256=1aMwEupTk68PfHrbY1v6il9p-cmMIMcdFk6Aqp9yU8M,1910
|
|
@@ -18,11 +18,11 @@ rcdl/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
18
18
|
rcdl/gui/__main__.py,sha256=Ti5dQqYxcyHuAOT8FGjYMhV0Y-j9Y-6utRkV7eRmyWA,68
|
|
19
19
|
rcdl/gui/db_viewer.py,sha256=0fM673d2JnWknFqVUDtDhzN6ojP1SGG06pO7T46IOHo,1060
|
|
20
20
|
rcdl/gui/gui.py,sha256=38mn30ZQPNN0lTyqh5AwIuszkNQ_SdE_FdRzkZXSEVE,1054
|
|
21
|
-
rcdl/gui/video_manager.py,sha256=
|
|
21
|
+
rcdl/gui/video_manager.py,sha256=nVravn1WAko5HP6gC03-v4kJKYZVUOIt5uOvs4PCOkU,5842
|
|
22
22
|
rcdl/interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
23
|
rcdl/interface/cli.py,sha256=mAKvphCoEXWtcnJfD5lsBGU5ooOKJM-G_Y4SeV9aUos,6094
|
|
24
|
-
rcdl/interface/ui.py,sha256=
|
|
25
|
-
rcdl-3.0.
|
|
26
|
-
rcdl-3.0.
|
|
27
|
-
rcdl-3.0.
|
|
28
|
-
rcdl-3.0.
|
|
24
|
+
rcdl/interface/ui.py,sha256=hR0JQME9ZER_GakFpi0OhK-7WB3wdx0U2KkRqkcGTkc,6078
|
|
25
|
+
rcdl-3.0.0b23.dist-info/entry_points.txt,sha256=TSFT1avCCO1d8pJnvuQLzX_1bA96uIDV_alKuruDN4E,42
|
|
26
|
+
rcdl-3.0.0b23.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
27
|
+
rcdl-3.0.0b23.dist-info/METADATA,sha256=m_FH-E7_pzu1h8AAWOQ8biqn4SN2azR7nCbO5tHnHeA,2945
|
|
28
|
+
rcdl-3.0.0b23.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|