library 3.2.6__tar.gz → 3.2.11__tar.gz
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.
- {library-3.2.6 → library-3.2.11}/.github/README.md +88 -5
- {library-3.2.6 → library-3.2.11}/PKG-INFO +140 -55
- {library-3.2.6 → library-3.2.11}/library/__main__.py +1 -2
- library-3.2.11/library/_version.py +25 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/gallery_backend.py +37 -35
- {library-3.2.6 → library-3.2.11}/library/createdb/links_add.py +11 -2
- {library-3.2.6 → library-3.2.11}/library/mediadb/download.py +11 -3
- {library-3.2.6 → library-3.2.11}/library/mediafiles/images_to_pdf.py +1 -1
- {library-3.2.6 → library-3.2.11}/library/mediafiles/process_image.py +1 -1
- library-3.2.11/library/mediafiles/torrents_dump.py +89 -0
- {library-3.2.6 → library-3.2.11}/library/mediafiles/unardel.py +39 -9
- {library-3.2.6 → library-3.2.11}/library/playback/play_actions.py +2 -1
- {library-3.2.6 → library-3.2.11}/library/playback/playback_control.py +2 -2
- {library-3.2.6 → library-3.2.11}/library/playback/torrents_info.py +40 -3
- {library-3.2.6 → library-3.2.11}/library/readme.py +28 -2
- library-3.2.11/library/text/extract_links.py +422 -0
- {library-3.2.6 → library-3.2.11}/library/usage.py +59 -2
- {library-3.2.6 → library-3.2.11}/library/utils/arggroups.py +101 -14
- {library-3.2.6 → library-3.2.11}/library/utils/consts.py +24 -0
- {library-3.2.6 → library-3.2.11}/library/utils/devices.py +12 -0
- {library-3.2.6 → library-3.2.11}/library/utils/printing.py +3 -6
- {library-3.2.6 → library-3.2.11}/library/utils/processes.py +9 -6
- {library-3.2.6 → library-3.2.11}/library/utils/shell_utils.py +12 -4
- {library-3.2.6 → library-3.2.11}/library/utils/strings.py +10 -6
- {library-3.2.6 → library-3.2.11}/library/utils/web.py +279 -11
- {library-3.2.6 → library-3.2.11}/pyproject.toml +23 -37
- library-3.2.11/pyproject.toml.orig +207 -0
- library-3.2.6/library/mediafiles/torrents_dump.py +0 -67
- library-3.2.6/library/text/extract_links.py +0 -274
- {library-3.2.6 → library-3.2.11}/LICENSE +0 -0
- {library-3.2.6 → library-3.2.11}/library/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/assets/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/assets/calibre.css +0 -0
- {library-3.2.6 → library-3.2.11}/library/assets/kotobago.png +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/av.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/computer_info.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/computers_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/fs_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/fs_add_metadata.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/gallery_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/getty_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/hn_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/nicotine_import.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/places_import.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/reddit_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/row_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/site_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/substack.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/subtitle.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/tables_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/tabs_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/tildes.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/torrents_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/tube_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/tube_backend.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/createdb/web_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/data/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/data/dictionary.pkl +0 -0
- {library-3.2.6 → library-3.2.11}/library/data/ffmpeg_errors.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/data/http_errors.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/data/imagemagick_errors.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/data/unar_errors.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/data/wordbank.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/data/yt_dlp_errors.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/editdb/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/editdb/dedupe_db.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/editdb/dedupe_media.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/editdb/merge_online_local.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/editdb/mpv_watchlater.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/editdb/pushshift.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/editdb/reddit_selftext.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/files/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/files/christen.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/files/sample_compare.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/files/sample_hash.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/files/similar_files.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/folders/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/folders/big_dirs.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/folders/filter_src.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/folders/merge_mv.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/folders/mergerfs_cp.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/folders/mount_stats.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/folders/move_list.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/folders/scatter.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/folders/similar_folders.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/fsdb/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/fsdb/disk_usage.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/fsdb/filesystem.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/fsdb/folder_stats.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/fsdb/search_db.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/lb.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/block.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/db_history.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/db_media.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/db_playlists.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/download_status.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/history.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/history_add.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/optimize_db.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/playlists.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/redownload.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/search.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediadb/stats.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediafiles/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediafiles/media_check.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediafiles/pdf_edit.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediafiles/process_ffmpeg.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediafiles/process_media.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediafiles/process_text.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/mediafiles/torrents_start.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/misc/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/misc/dedupe_czkawka.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/misc/export_text.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/misc/search_help.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/multidb/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/multidb/allocate_torrents.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/multidb/copy_play_counts.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/multidb/merge_dbs.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/playback/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/playback/links_open.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/playback/media_player.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/playback/media_printer.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/playback/post_actions.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/playback/surf.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/playback/tabs_open.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/playback/torrents_remaining.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/tablefiles/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/tablefiles/columns.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/tablefiles/eda.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/tablefiles/incremental_diff.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/tablefiles/markdown_tables.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/tablefiles/mcda.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/tablefiles/plot.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/text/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/text/cluster_sort.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/text/combinations.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/text/expand_links.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/text/extract_text.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/text/json_keys_rename.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/text/markdown_links.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/text/nouns.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/text/regex_sort.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/text/timestamps.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/__init__.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/arg_utils.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/argparse_utils.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/date_utils.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/db_utils.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/file_utils.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/filter_engine.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/gui.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/iterables.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/log_utils.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/mpv_utils.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/nums.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/objects.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/path_utils.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/pd_utils.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/remote_processes.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/sql_utils.py +0 -0
- {library-3.2.6 → library-3.2.11}/library/utils/sqlgroups.py +0 -0
|
@@ -10,7 +10,9 @@ tracking online video playlists (eg. YouTube subscriptions) and scheduling brows
|
|
|
10
10
|
|
|
11
11
|
[](https://pepy.tech/project/library)
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Getting started
|
|
14
|
+
|
|
15
|
+
<details><summary>Install</summary>
|
|
14
16
|
|
|
15
17
|
Linux recommended but [Windows setup instructions](./Windows.md) available.
|
|
16
18
|
|
|
@@ -24,7 +26,31 @@ Required: `ffmpeg`
|
|
|
24
26
|
|
|
25
27
|
Some features work better with: `mpv`, `fd-find`, `fish`
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
Optional Python extras are grouped under `library[deluxe]`. This includes
|
|
30
|
+
`gallery-dl` (used by `gallery-add`), `internetarchive` (used for Internet
|
|
31
|
+
Archive downloads), and `cdx_toolkit` (used by the `--webcache`/`--wayback`
|
|
32
|
+
CDX extractor):
|
|
33
|
+
|
|
34
|
+
pip install "library[deluxe]"
|
|
35
|
+
|
|
36
|
+
Torrent metadata commands (`torrents-add` and `torrents-dump`) require the
|
|
37
|
+
`libtorrent` Python bindings. They are included by `library[deluxe]` when using
|
|
38
|
+
Python 3.12 or 3.13; Python 3.14 wheels are not available yet, so use Python
|
|
39
|
+
3.13 for torrent support.
|
|
40
|
+
|
|
41
|
+
If the PyPI wheel is unavailable for your Python or platform, these system
|
|
42
|
+
packages provide the bindings:
|
|
43
|
+
|
|
44
|
+
* Debian/Ubuntu: `sudo apt install python3-libtorrent`
|
|
45
|
+
* Fedora: `sudo dnf install rb_libtorrent-python3`
|
|
46
|
+
* macOS/Homebrew: `brew install libtorrent-rasterbar`
|
|
47
|
+
|
|
48
|
+
The Debian, Fedora, and Homebrew packages are built for their system or
|
|
49
|
+
Homebrew Python and may not be importable from a separate uv virtualenv. There
|
|
50
|
+
is no official Scoop package for the Python bindings; on Windows, use Python
|
|
51
|
+
3.13 and `pip install "library[deluxe]"`.
|
|
52
|
+
|
|
53
|
+
</details>
|
|
28
54
|
|
|
29
55
|
<details><summary>Local media</summary>
|
|
30
56
|
|
|
@@ -99,7 +125,7 @@ To stop playing press Ctrl+C in either the terminal or mpv
|
|
|
99
125
|
<details><summary>List all subcommands</summary>
|
|
100
126
|
|
|
101
127
|
$ library
|
|
102
|
-
library (v3.2.
|
|
128
|
+
library (v3.2.011; 102 subcommands)
|
|
103
129
|
|
|
104
130
|
Create database subcommands:
|
|
105
131
|
╭─────────────────┬──────────────────────────────────────────╮
|
|
@@ -797,6 +823,14 @@ BTW, for some cols like time_deleted you'll need to specify a where clause so th
|
|
|
797
823
|
--page-key start --page-start 0 --page-step 50 --fixed-pages 14 --stop-pages-no-match 1 \
|
|
798
824
|
plab.db https://plab/forum/tracker.php?o=(string replace ' ' \n -- 1 4 7 10 15)&s=2&tm=-1&f=(string replace ' ' \n -- 1670 1768 60 1671 1644 1672 1111 508 555 1112 1718 1143 1717 1851 1713 1712 1775 1674 902 1675 36 1830 1803 1831 1741 1676 1677 1780 1110 1124 1784 1769 1793 1797 1804 1819 1825 1836 1842 1846 1857 1861 1867 1451 1788 1789 1792 1798 1805 1820 1826 1837 1843 1847 1856 1862 1868 284 1853 1823 1800 1801 1719 997 1818 1849 1711 1791 1762)
|
|
799
825
|
|
|
826
|
+
Recursively add every link on a site (glob excludes prune subtrees from the crawl)
|
|
827
|
+
|
|
828
|
+
library links-add links.db --recursive https://example.com/docs/ --path-exclude '*/tags/*'
|
|
829
|
+
|
|
830
|
+
Add every archived link for a site from the Internet Archive CDX index
|
|
831
|
+
|
|
832
|
+
library links-add links.db --webcache https://example.com/docs/
|
|
833
|
+
|
|
800
834
|
|
|
801
835
|
</details>
|
|
802
836
|
|
|
@@ -1130,6 +1164,31 @@ BTW, for some cols like time_deleted you'll need to specify a where clause so th
|
|
|
1130
1164
|
library links https://en.wikipedia.org/wiki/List_of_bacon_dishes --path-include https://en.wikipedia.org/wiki/ --after-include famous
|
|
1131
1165
|
https://en.wikipedia.org/wiki/Omelette
|
|
1132
1166
|
|
|
1167
|
+
Download the filtered links. Internet Archive details pages use the Internet Archive downloader and preserve all original files:
|
|
1168
|
+
|
|
1169
|
+
library extract-links --download https://readrare.com/
|
|
1170
|
+
|
|
1171
|
+
Mirror a site recursively. Only links within the same domain and parent directory as the given
|
|
1172
|
+
path are followed; links pointing elsewhere are downloaded but not followed. Includes/excludes
|
|
1173
|
+
accept globs, so you can prune whole subtrees while crawling:
|
|
1174
|
+
|
|
1175
|
+
library links --recursive --download https://example.com/docs/
|
|
1176
|
+
library links -R --download https://example.com/docs/ --path-exclude '*/tag/*' '*/tags/*'
|
|
1177
|
+
|
|
1178
|
+
Extract links from a web archive CDX index instead of crawling live pages. Internet Archive
|
|
1179
|
+
Wayback snapshots are emitted by default. Wayback URLs are collapsed to their original
|
|
1180
|
+
archived URL while crawling: sibling pages that only exist under a different timestamp are
|
|
1181
|
+
still followed, but multiple captures of the same page are collapsed so only one copy of
|
|
1182
|
+
each page is downloaded. Use --webcache-from/--webcache-to to target a time period:
|
|
1183
|
+
|
|
1184
|
+
library links --webcache https://example.com/docs/
|
|
1185
|
+
library links --webcache --recursive --download https://example.com/docs/
|
|
1186
|
+
library links --webcache --webcache-source cc https://example.com/docs/
|
|
1187
|
+
library links --webcache --webcache-from 2020 --webcache-to 2021 https://example.com/docs/
|
|
1188
|
+
|
|
1189
|
+
Common tracking and analytics URLs, including Google Tag Manager and Google Analytics,
|
|
1190
|
+
are excluded by default. Use --path-exclude to replace the default exclusions when needed.
|
|
1191
|
+
|
|
1133
1192
|
Read from local clipboard and filter out links based on nearby plain text
|
|
1134
1193
|
|
|
1135
1194
|
library links --local-html (cb -t text/html | psub) --after-exclude paranormal spooky horror podcast tech fantasy supernatural lecture sport
|
|
@@ -2178,10 +2237,14 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
2178
2237
|
<details><summary>Print torrent file info</summary>
|
|
2179
2238
|
|
|
2180
2239
|
$ library torrents-dump -h
|
|
2181
|
-
usage: library torrents-dump PATH ...
|
|
2240
|
+
usage: library torrents-dump [--trackers] PATH ...
|
|
2182
2241
|
|
|
2183
2242
|
View torrent file metadata via libtorrent
|
|
2184
2243
|
|
|
2244
|
+
Aggregate torrent metadata by tracker domain:
|
|
2245
|
+
|
|
2246
|
+
library torrents-dump --trackers PATH ...
|
|
2247
|
+
|
|
2185
2248
|
|
|
2186
2249
|
</details>
|
|
2187
2250
|
|
|
@@ -2316,7 +2379,7 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
2316
2379
|
| /home/xk/github/xk/lb/.ruff_cache/ | 19.5 kB | 100 |
|
|
2317
2380
|
| /home/xk/github/xk/lb/.gitattributes | 119 Bytes | |
|
|
2318
2381
|
| /home/xk/github/xk/lb/.mypy_cache/ | 280 Bytes | 4 |
|
|
2319
|
-
| /home/xk/github/xk/lb/.
|
|
2382
|
+
| /home/xk/github/xk/lb/.venv | 15 Bytes | |
|
|
2320
2383
|
|
|
2321
2384
|
Only include files with a specific depth
|
|
2322
2385
|
|
|
@@ -2489,6 +2552,17 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
2489
2552
|
library download dl.db --include https://www.youtube.com/watch?v=YE7VzlLtp-4
|
|
2490
2553
|
library download dl.db -s https://www.youtube.com/watch?v=YE7VzlLtp-4 # equivalent
|
|
2491
2554
|
|
|
2555
|
+
Recursively download a site (filesystem profile). Only links within the same domain and
|
|
2556
|
+
parent directory as the seed are followed; other links are downloaded but not followed.
|
|
2557
|
+
|
|
2558
|
+
library download links.db --filesystem --recursive --prefix ~/mirror/ https://example.com/docs/
|
|
2559
|
+
|
|
2560
|
+
Download a site's archived pages from the Internet Archive Wayback Machine using the CDX API.
|
|
2561
|
+
`--webcache` implies `--links`; add `--recursive` to also parse the archived pages for
|
|
2562
|
+
further links:
|
|
2563
|
+
|
|
2564
|
+
library download links.db --filesystem --webcache --prefix ~/mirror/ https://example.com/docs/
|
|
2565
|
+
|
|
2492
2566
|
Maximizing the variety of subdomains
|
|
2493
2567
|
|
|
2494
2568
|
library download photos.db --photos --image --sort "ROW_NUMBER() OVER ( PARTITION BY SUBSTR(m.path, INSTR(m.path, '//') + 2, INSTR( SUBSTR(m.path, INSTR(m.path, '//') + 2), '/') - 1) )"
|
|
@@ -3054,6 +3128,10 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
3054
3128
|
library torrents --dl --different-drives
|
|
3055
3129
|
library torrents --dl --different-drives /mnt/d4/
|
|
3056
3130
|
|
|
3131
|
+
Find incomplete torrents whose temp and final paths use the same drive:
|
|
3132
|
+
|
|
3133
|
+
library torrents --dl --same-drives
|
|
3134
|
+
|
|
3057
3135
|
Aggregate torrent info (torrents-status)
|
|
3058
3136
|
|
|
3059
3137
|
library torrents -pa
|
|
@@ -3070,6 +3148,10 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
3070
3148
|
|
|
3071
3149
|
library torrents --dl --progress=+10% --force-start
|
|
3072
3150
|
|
|
3151
|
+
Find torrents with a recorded completion timestamp
|
|
3152
|
+
|
|
3153
|
+
library torrents --completed
|
|
3154
|
+
|
|
3073
3155
|
Stop completed downloads
|
|
3074
3156
|
|
|
3075
3157
|
library torrents -S+5MiB --seeders=+5 --time-stalled=+45days --time-active=+180days --stop
|
|
@@ -3094,6 +3176,7 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
3094
3176
|
When --delete-rows is provided, the metadata is removed from qBittorrent
|
|
3095
3177
|
When --delete-files is provided, the downloaded files are deleted
|
|
3096
3178
|
When --delete-incomplete 80% is provided, any files that were downloaded less than 80% are deleted
|
|
3179
|
+
When --reset-progress is provided, the downloaded files are deleted and progress is reset without removing the torrents
|
|
3097
3180
|
|
|
3098
3181
|
|
|
3099
3182
|
</details>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: library
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.11
|
|
4
4
|
Summary: xk media library
|
|
5
|
-
Author
|
|
5
|
+
Author: Jacob Chapman
|
|
6
|
+
Author-email: Jacob Chapman <7908073+chapmanjacobd@users.noreply.github.com>
|
|
6
7
|
License: BSD 3-Clause License
|
|
7
8
|
|
|
8
9
|
Copyright (c) 2024, Jacob Chapman
|
|
@@ -31,16 +32,10 @@ License: BSD 3-Clause License
|
|
|
31
32
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
32
33
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
33
34
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
34
|
-
|
|
35
|
-
Project-URL: documentation, https://github.com/chapmanjacobd/library#usage
|
|
36
|
-
Project-URL: homepage, https://github.com/chapmanjacobd/library#readme
|
|
37
|
-
Project-URL: repository, https://github.com/chapmanjacobd/library/
|
|
38
|
-
Requires-Python: >=3.12
|
|
39
35
|
Requires-Dist: beautifulsoup4>=4.10.0
|
|
40
36
|
Requires-Dist: sqlite-utils>=3.38
|
|
41
37
|
Requires-Dist: ipython>=9.0.0
|
|
42
38
|
Requires-Dist: ffmpeg-python
|
|
43
|
-
Requires-Dist: gallery-dl
|
|
44
39
|
Requires-Dist: yt-dlp[default]
|
|
45
40
|
Requires-Dist: natsort
|
|
46
41
|
Requires-Dist: charset-normalizer
|
|
@@ -61,49 +56,56 @@ Requires-Dist: screeninfo
|
|
|
61
56
|
Requires-Dist: tabulate
|
|
62
57
|
Requires-Dist: tinytag
|
|
63
58
|
Requires-Dist: tldextract
|
|
64
|
-
Requires-Dist: pyreadline3;
|
|
65
|
-
|
|
66
|
-
Requires-Dist:
|
|
67
|
-
Requires-Dist:
|
|
68
|
-
Requires-Dist:
|
|
69
|
-
|
|
70
|
-
Requires-Dist:
|
|
71
|
-
Requires-Dist:
|
|
72
|
-
Requires-Dist:
|
|
73
|
-
Requires-Dist:
|
|
74
|
-
Requires-Dist:
|
|
75
|
-
Requires-Dist:
|
|
59
|
+
Requires-Dist: pyreadline3 ; sys_platform == 'win32'
|
|
60
|
+
Requires-Dist: aiohttp ; extra == 'deluxe'
|
|
61
|
+
Requires-Dist: annoy ; extra == 'deluxe'
|
|
62
|
+
Requires-Dist: catt ; extra == 'deluxe'
|
|
63
|
+
Requires-Dist: cdx-toolkit ; extra == 'deluxe'
|
|
64
|
+
Requires-Dist: curl-cffi ; extra == 'deluxe'
|
|
65
|
+
Requires-Dist: gallery-dl ; extra == 'deluxe'
|
|
66
|
+
Requires-Dist: geopandas ; extra == 'deluxe'
|
|
67
|
+
Requires-Dist: img2pdf ; extra == 'deluxe'
|
|
68
|
+
Requires-Dist: internetarchive ; extra == 'deluxe'
|
|
69
|
+
Requires-Dist: ocrmypdf ; extra == 'deluxe'
|
|
70
|
+
Requires-Dist: openpyxl ; extra == 'deluxe'
|
|
71
|
+
Requires-Dist: paramiko ; extra == 'deluxe'
|
|
72
|
+
Requires-Dist: pdf2image ; extra == 'deluxe'
|
|
73
|
+
Requires-Dist: pillow ; extra == 'deluxe'
|
|
74
|
+
Requires-Dist: pyexiftool ; extra == 'deluxe'
|
|
75
|
+
Requires-Dist: pymcdm ; extra == 'deluxe'
|
|
76
|
+
Requires-Dist: pyvirtualdisplay ; extra == 'deluxe'
|
|
77
|
+
Requires-Dist: qbittorrent-api ; extra == 'deluxe'
|
|
78
|
+
Requires-Dist: scikit-learn ; extra == 'deluxe'
|
|
79
|
+
Requires-Dist: selenium ; extra == 'deluxe'
|
|
80
|
+
Requires-Dist: libtorrent ; python_full_version < '3.14' and extra == 'deluxe'
|
|
81
|
+
Requires-Dist: tqdm ; extra == 'deluxe'
|
|
82
|
+
Requires-Dist: wordllama>=0.2.7.post0 ; extra == 'deluxe'
|
|
83
|
+
Requires-Dist: xattr ; sys_platform != 'win32' and extra == 'deluxe'
|
|
84
|
+
Requires-Dist: black ; extra == 'dev'
|
|
85
|
+
Requires-Dist: isort ; extra == 'dev'
|
|
86
|
+
Requires-Dist: ssort ; extra == 'dev'
|
|
87
|
+
Requires-Dist: brotab ; extra == 'fat'
|
|
88
|
+
Requires-Dist: camelot-py>=0.11.0 ; extra == 'fat'
|
|
89
|
+
Requires-Dist: ghostscript ; extra == 'fat'
|
|
90
|
+
Requires-Dist: opencv-python ; extra == 'fat'
|
|
91
|
+
Requires-Dist: orjson ; extra == 'fat'
|
|
92
|
+
Requires-Dist: selenium-wire-lw ; extra == 'fat'
|
|
93
|
+
Requires-Dist: subliminal ; extra == 'fat'
|
|
94
|
+
Requires-Dist: textract-py3==2.0.1 ; extra == 'fat'
|
|
95
|
+
Requires-Dist: ruff ; extra == 'test'
|
|
96
|
+
Requires-Dist: pytest ; extra == 'test'
|
|
97
|
+
Requires-Dist: pytest-regressions ; extra == 'test'
|
|
98
|
+
Requires-Dist: freezegun ; extra == 'test'
|
|
99
|
+
Requires-Dist: pandas ; extra == 'test'
|
|
100
|
+
Requires-Dist: pyfakefs ; extra == 'test'
|
|
101
|
+
Requires-Python: >=3.12
|
|
102
|
+
Project-URL: documentation, https://github.com/chapmanjacobd/library#usage
|
|
103
|
+
Project-URL: homepage, https://github.com/chapmanjacobd/library#readme
|
|
104
|
+
Project-URL: repository, https://github.com/chapmanjacobd/library/
|
|
76
105
|
Provides-Extra: deluxe
|
|
77
|
-
|
|
78
|
-
Requires-Dist: annoy; extra == "deluxe"
|
|
79
|
-
Requires-Dist: catt; extra == "deluxe"
|
|
80
|
-
Requires-Dist: curl-cffi; extra == "deluxe"
|
|
81
|
-
Requires-Dist: geopandas; extra == "deluxe"
|
|
82
|
-
Requires-Dist: img2pdf; extra == "deluxe"
|
|
83
|
-
Requires-Dist: ocrmypdf; extra == "deluxe"
|
|
84
|
-
Requires-Dist: openpyxl; extra == "deluxe"
|
|
85
|
-
Requires-Dist: paramiko; extra == "deluxe"
|
|
86
|
-
Requires-Dist: pdf2image; extra == "deluxe"
|
|
87
|
-
Requires-Dist: pillow; extra == "deluxe"
|
|
88
|
-
Requires-Dist: PyExifTool; extra == "deluxe"
|
|
89
|
-
Requires-Dist: pymcdm; extra == "deluxe"
|
|
90
|
-
Requires-Dist: pyvirtualdisplay; extra == "deluxe"
|
|
91
|
-
Requires-Dist: qbittorrent-api; extra == "deluxe"
|
|
92
|
-
Requires-Dist: scikit-learn; extra == "deluxe"
|
|
93
|
-
Requires-Dist: selenium; extra == "deluxe"
|
|
94
|
-
Requires-Dist: libtorrent; extra == "deluxe"
|
|
95
|
-
Requires-Dist: tqdm; extra == "deluxe"
|
|
96
|
-
Requires-Dist: wordllama>=0.2.7.post0; extra == "deluxe"
|
|
97
|
-
Requires-Dist: xattr; extra == "deluxe"
|
|
106
|
+
Provides-Extra: dev
|
|
98
107
|
Provides-Extra: fat
|
|
99
|
-
|
|
100
|
-
Requires-Dist: camelot-py>=0.11.0; extra == "fat"
|
|
101
|
-
Requires-Dist: ghostscript; extra == "fat"
|
|
102
|
-
Requires-Dist: opencv-python; extra == "fat"
|
|
103
|
-
Requires-Dist: orjson; extra == "fat"
|
|
104
|
-
Requires-Dist: selenium-wire-lw; extra == "fat"
|
|
105
|
-
Requires-Dist: subliminal; extra == "fat"
|
|
106
|
-
Requires-Dist: textract-py3==2.0.1; extra == "fat"
|
|
108
|
+
Provides-Extra: test
|
|
107
109
|
Description-Content-Type: text/markdown
|
|
108
110
|
|
|
109
111
|
# library (media toolkit)
|
|
@@ -118,7 +120,9 @@ tracking online video playlists (eg. YouTube subscriptions) and scheduling brows
|
|
|
118
120
|
|
|
119
121
|
[](https://pepy.tech/project/library)
|
|
120
122
|
|
|
121
|
-
##
|
|
123
|
+
## Getting started
|
|
124
|
+
|
|
125
|
+
<details><summary>Install</summary>
|
|
122
126
|
|
|
123
127
|
Linux recommended but [Windows setup instructions](./Windows.md) available.
|
|
124
128
|
|
|
@@ -132,7 +136,31 @@ Required: `ffmpeg`
|
|
|
132
136
|
|
|
133
137
|
Some features work better with: `mpv`, `fd-find`, `fish`
|
|
134
138
|
|
|
135
|
-
|
|
139
|
+
Optional Python extras are grouped under `library[deluxe]`. This includes
|
|
140
|
+
`gallery-dl` (used by `gallery-add`), `internetarchive` (used for Internet
|
|
141
|
+
Archive downloads), and `cdx_toolkit` (used by the `--webcache`/`--wayback`
|
|
142
|
+
CDX extractor):
|
|
143
|
+
|
|
144
|
+
pip install "library[deluxe]"
|
|
145
|
+
|
|
146
|
+
Torrent metadata commands (`torrents-add` and `torrents-dump`) require the
|
|
147
|
+
`libtorrent` Python bindings. They are included by `library[deluxe]` when using
|
|
148
|
+
Python 3.12 or 3.13; Python 3.14 wheels are not available yet, so use Python
|
|
149
|
+
3.13 for torrent support.
|
|
150
|
+
|
|
151
|
+
If the PyPI wheel is unavailable for your Python or platform, these system
|
|
152
|
+
packages provide the bindings:
|
|
153
|
+
|
|
154
|
+
* Debian/Ubuntu: `sudo apt install python3-libtorrent`
|
|
155
|
+
* Fedora: `sudo dnf install rb_libtorrent-python3`
|
|
156
|
+
* macOS/Homebrew: `brew install libtorrent-rasterbar`
|
|
157
|
+
|
|
158
|
+
The Debian, Fedora, and Homebrew packages are built for their system or
|
|
159
|
+
Homebrew Python and may not be importable from a separate uv virtualenv. There
|
|
160
|
+
is no official Scoop package for the Python bindings; on Windows, use Python
|
|
161
|
+
3.13 and `pip install "library[deluxe]"`.
|
|
162
|
+
|
|
163
|
+
</details>
|
|
136
164
|
|
|
137
165
|
<details><summary>Local media</summary>
|
|
138
166
|
|
|
@@ -207,7 +235,7 @@ To stop playing press Ctrl+C in either the terminal or mpv
|
|
|
207
235
|
<details><summary>List all subcommands</summary>
|
|
208
236
|
|
|
209
237
|
$ library
|
|
210
|
-
library (v3.2.
|
|
238
|
+
library (v3.2.011; 102 subcommands)
|
|
211
239
|
|
|
212
240
|
Create database subcommands:
|
|
213
241
|
╭─────────────────┬──────────────────────────────────────────╮
|
|
@@ -905,6 +933,14 @@ BTW, for some cols like time_deleted you'll need to specify a where clause so th
|
|
|
905
933
|
--page-key start --page-start 0 --page-step 50 --fixed-pages 14 --stop-pages-no-match 1 \
|
|
906
934
|
plab.db https://plab/forum/tracker.php?o=(string replace ' ' \n -- 1 4 7 10 15)&s=2&tm=-1&f=(string replace ' ' \n -- 1670 1768 60 1671 1644 1672 1111 508 555 1112 1718 1143 1717 1851 1713 1712 1775 1674 902 1675 36 1830 1803 1831 1741 1676 1677 1780 1110 1124 1784 1769 1793 1797 1804 1819 1825 1836 1842 1846 1857 1861 1867 1451 1788 1789 1792 1798 1805 1820 1826 1837 1843 1847 1856 1862 1868 284 1853 1823 1800 1801 1719 997 1818 1849 1711 1791 1762)
|
|
907
935
|
|
|
936
|
+
Recursively add every link on a site (glob excludes prune subtrees from the crawl)
|
|
937
|
+
|
|
938
|
+
library links-add links.db --recursive https://example.com/docs/ --path-exclude '*/tags/*'
|
|
939
|
+
|
|
940
|
+
Add every archived link for a site from the Internet Archive CDX index
|
|
941
|
+
|
|
942
|
+
library links-add links.db --webcache https://example.com/docs/
|
|
943
|
+
|
|
908
944
|
|
|
909
945
|
</details>
|
|
910
946
|
|
|
@@ -1238,6 +1274,31 @@ BTW, for some cols like time_deleted you'll need to specify a where clause so th
|
|
|
1238
1274
|
library links https://en.wikipedia.org/wiki/List_of_bacon_dishes --path-include https://en.wikipedia.org/wiki/ --after-include famous
|
|
1239
1275
|
https://en.wikipedia.org/wiki/Omelette
|
|
1240
1276
|
|
|
1277
|
+
Download the filtered links. Internet Archive details pages use the Internet Archive downloader and preserve all original files:
|
|
1278
|
+
|
|
1279
|
+
library extract-links --download https://readrare.com/
|
|
1280
|
+
|
|
1281
|
+
Mirror a site recursively. Only links within the same domain and parent directory as the given
|
|
1282
|
+
path are followed; links pointing elsewhere are downloaded but not followed. Includes/excludes
|
|
1283
|
+
accept globs, so you can prune whole subtrees while crawling:
|
|
1284
|
+
|
|
1285
|
+
library links --recursive --download https://example.com/docs/
|
|
1286
|
+
library links -R --download https://example.com/docs/ --path-exclude '*/tag/*' '*/tags/*'
|
|
1287
|
+
|
|
1288
|
+
Extract links from a web archive CDX index instead of crawling live pages. Internet Archive
|
|
1289
|
+
Wayback snapshots are emitted by default. Wayback URLs are collapsed to their original
|
|
1290
|
+
archived URL while crawling: sibling pages that only exist under a different timestamp are
|
|
1291
|
+
still followed, but multiple captures of the same page are collapsed so only one copy of
|
|
1292
|
+
each page is downloaded. Use --webcache-from/--webcache-to to target a time period:
|
|
1293
|
+
|
|
1294
|
+
library links --webcache https://example.com/docs/
|
|
1295
|
+
library links --webcache --recursive --download https://example.com/docs/
|
|
1296
|
+
library links --webcache --webcache-source cc https://example.com/docs/
|
|
1297
|
+
library links --webcache --webcache-from 2020 --webcache-to 2021 https://example.com/docs/
|
|
1298
|
+
|
|
1299
|
+
Common tracking and analytics URLs, including Google Tag Manager and Google Analytics,
|
|
1300
|
+
are excluded by default. Use --path-exclude to replace the default exclusions when needed.
|
|
1301
|
+
|
|
1241
1302
|
Read from local clipboard and filter out links based on nearby plain text
|
|
1242
1303
|
|
|
1243
1304
|
library links --local-html (cb -t text/html | psub) --after-exclude paranormal spooky horror podcast tech fantasy supernatural lecture sport
|
|
@@ -2286,10 +2347,14 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
2286
2347
|
<details><summary>Print torrent file info</summary>
|
|
2287
2348
|
|
|
2288
2349
|
$ library torrents-dump -h
|
|
2289
|
-
usage: library torrents-dump PATH ...
|
|
2350
|
+
usage: library torrents-dump [--trackers] PATH ...
|
|
2290
2351
|
|
|
2291
2352
|
View torrent file metadata via libtorrent
|
|
2292
2353
|
|
|
2354
|
+
Aggregate torrent metadata by tracker domain:
|
|
2355
|
+
|
|
2356
|
+
library torrents-dump --trackers PATH ...
|
|
2357
|
+
|
|
2293
2358
|
|
|
2294
2359
|
</details>
|
|
2295
2360
|
|
|
@@ -2424,7 +2489,7 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
2424
2489
|
| /home/xk/github/xk/lb/.ruff_cache/ | 19.5 kB | 100 |
|
|
2425
2490
|
| /home/xk/github/xk/lb/.gitattributes | 119 Bytes | |
|
|
2426
2491
|
| /home/xk/github/xk/lb/.mypy_cache/ | 280 Bytes | 4 |
|
|
2427
|
-
| /home/xk/github/xk/lb/.
|
|
2492
|
+
| /home/xk/github/xk/lb/.venv | 15 Bytes | |
|
|
2428
2493
|
|
|
2429
2494
|
Only include files with a specific depth
|
|
2430
2495
|
|
|
@@ -2597,6 +2662,17 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
2597
2662
|
library download dl.db --include https://www.youtube.com/watch?v=YE7VzlLtp-4
|
|
2598
2663
|
library download dl.db -s https://www.youtube.com/watch?v=YE7VzlLtp-4 # equivalent
|
|
2599
2664
|
|
|
2665
|
+
Recursively download a site (filesystem profile). Only links within the same domain and
|
|
2666
|
+
parent directory as the seed are followed; other links are downloaded but not followed.
|
|
2667
|
+
|
|
2668
|
+
library download links.db --filesystem --recursive --prefix ~/mirror/ https://example.com/docs/
|
|
2669
|
+
|
|
2670
|
+
Download a site's archived pages from the Internet Archive Wayback Machine using the CDX API.
|
|
2671
|
+
`--webcache` implies `--links`; add `--recursive` to also parse the archived pages for
|
|
2672
|
+
further links:
|
|
2673
|
+
|
|
2674
|
+
library download links.db --filesystem --webcache --prefix ~/mirror/ https://example.com/docs/
|
|
2675
|
+
|
|
2600
2676
|
Maximizing the variety of subdomains
|
|
2601
2677
|
|
|
2602
2678
|
library download photos.db --photos --image --sort "ROW_NUMBER() OVER ( PARTITION BY SUBSTR(m.path, INSTR(m.path, '//') + 2, INSTR( SUBSTR(m.path, INSTR(m.path, '//') + 2), '/') - 1) )"
|
|
@@ -3162,6 +3238,10 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
3162
3238
|
library torrents --dl --different-drives
|
|
3163
3239
|
library torrents --dl --different-drives /mnt/d4/
|
|
3164
3240
|
|
|
3241
|
+
Find incomplete torrents whose temp and final paths use the same drive:
|
|
3242
|
+
|
|
3243
|
+
library torrents --dl --same-drives
|
|
3244
|
+
|
|
3165
3245
|
Aggregate torrent info (torrents-status)
|
|
3166
3246
|
|
|
3167
3247
|
library torrents -pa
|
|
@@ -3178,6 +3258,10 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
3178
3258
|
|
|
3179
3259
|
library torrents --dl --progress=+10% --force-start
|
|
3180
3260
|
|
|
3261
|
+
Find torrents with a recorded completion timestamp
|
|
3262
|
+
|
|
3263
|
+
library torrents --completed
|
|
3264
|
+
|
|
3181
3265
|
Stop completed downloads
|
|
3182
3266
|
|
|
3183
3267
|
library torrents -S+5MiB --seeders=+5 --time-stalled=+45days --time-active=+180days --stop
|
|
@@ -3202,6 +3286,7 @@ Inspired somewhat by https://nikkhokkho.sourceforge.io/?page=FileOptimizer
|
|
|
3202
3286
|
When --delete-rows is provided, the metadata is removed from qBittorrent
|
|
3203
3287
|
When --delete-files is provided, the downloaded files are deleted
|
|
3204
3288
|
When --delete-incomplete 80% is provided, any files that were downloaded less than 80% are deleted
|
|
3289
|
+
When --reset-progress is provided, the downloaded files are deleted and progress is reset without removing the torrents
|
|
3205
3290
|
|
|
3206
3291
|
|
|
3207
3292
|
</details>
|
|
@@ -2,11 +2,10 @@ import argparse, importlib, os, sys, textwrap
|
|
|
2
2
|
|
|
3
3
|
from tabulate import tabulate
|
|
4
4
|
|
|
5
|
+
from library._version import __version__
|
|
5
6
|
from library.utils import argparse_utils, iterables
|
|
6
7
|
from library.utils.log_utils import log
|
|
7
8
|
|
|
8
|
-
__version__ = "3.2.006"
|
|
9
|
-
|
|
10
9
|
progs = {
|
|
11
10
|
"Create database subcommands": {
|
|
12
11
|
"fs_add": "Add local media",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Copyright (c) 2026, Jacob Chapman
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError
|
|
4
|
+
from importlib.metadata import version as installed_version
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import tomllib
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_version() -> str:
|
|
10
|
+
pyproject_path = Path(__file__).resolve().parents[1] / "pyproject.toml"
|
|
11
|
+
if pyproject_path.is_file():
|
|
12
|
+
with pyproject_path.open("rb") as pyproject_file:
|
|
13
|
+
project_version = tomllib.load(pyproject_file)["project"].get("version")
|
|
14
|
+
if isinstance(project_version, str):
|
|
15
|
+
return project_version
|
|
16
|
+
message = f"Missing string project version in {pyproject_path}"
|
|
17
|
+
raise RuntimeError(message)
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
return installed_version("library")
|
|
21
|
+
except PackageNotFoundError as error:
|
|
22
|
+
raise RuntimeError("Unable to determine the library version") from error
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
__version__ = get_version()
|
|
@@ -2,9 +2,6 @@ import os
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from types import ModuleType
|
|
4
4
|
|
|
5
|
-
import gallery_dl
|
|
6
|
-
from gallery_dl.job import Job
|
|
7
|
-
|
|
8
5
|
from library.mediadb import db_media, db_playlists
|
|
9
6
|
from library.utils import consts, printing, strings
|
|
10
7
|
from library.utils.log_utils import log
|
|
@@ -142,52 +139,57 @@ def download(args, m):
|
|
|
142
139
|
)
|
|
143
140
|
|
|
144
141
|
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
def url_job_class(gallery_dl):
|
|
143
|
+
# gallery_dl is an optional (deluxe) dependency, so the Job base class
|
|
144
|
+
# can only be resolved once gallery_dl has been imported
|
|
145
|
+
class UrlJob(gallery_dl.job.Job):
|
|
146
|
+
resolve = 1 # depth of queue resolution
|
|
147
147
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
148
|
+
def __init__(self, url, parent=None, resolve=None):
|
|
149
|
+
super().__init__(url, parent)
|
|
150
|
+
self.results = []
|
|
151
|
+
self.visited = set()
|
|
152
|
+
if resolve is not None:
|
|
153
|
+
self.resolve = resolve
|
|
154
154
|
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
if self.resolve > 0:
|
|
156
|
+
self.handle_queue = self.handle_queue_resolve
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
def handle_url(self, url, kwdict):
|
|
159
|
+
self.results.append((url, kwdict))
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
def handle_queue(self, url, kwdict):
|
|
162
|
+
# unresolved queue entry
|
|
163
|
+
self.results.append((url, kwdict))
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
def handle_queue_resolve(self, url, kwdict):
|
|
166
|
+
if url in self.visited:
|
|
167
|
+
return
|
|
168
|
+
self.visited.add(url)
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
170
|
+
cls = kwdict.get("_extractor")
|
|
171
|
+
if cls:
|
|
172
|
+
extr = cls.from_url(url)
|
|
173
|
+
else:
|
|
174
|
+
extr = self.extractor.find(url)
|
|
175
175
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
if not extr:
|
|
177
|
+
self.results.append((url, kwdict))
|
|
178
|
+
return
|
|
179
179
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
180
|
+
job = self.__class__(extr, self, self.resolve - 1)
|
|
181
|
+
job.results = self.results # shared accumulator
|
|
182
|
+
job.visited = self.visited # shared visited set
|
|
183
|
+
job.run()
|
|
184
|
+
|
|
185
|
+
return UrlJob
|
|
184
186
|
|
|
185
187
|
|
|
186
188
|
def get_playlist_metadata(args, playlist_path):
|
|
187
189
|
gallery_dl = load_module_level_gallery_dl(args)
|
|
188
190
|
|
|
189
191
|
added_media_count = 0
|
|
190
|
-
job =
|
|
192
|
+
job = url_job_class(gallery_dl)(playlist_path)
|
|
191
193
|
job.run()
|
|
192
194
|
|
|
193
195
|
is_playlist = len(job.results) > 1
|
|
@@ -130,6 +130,7 @@ To compensate for this the script will only continue fetching pages until there
|
|
|
130
130
|
)
|
|
131
131
|
|
|
132
132
|
arggroups.filter_links(parser)
|
|
133
|
+
arggroups.spider(parser)
|
|
133
134
|
|
|
134
135
|
arggroups.requests(parser)
|
|
135
136
|
arggroups.selenium(parser)
|
|
@@ -254,6 +255,8 @@ def extractor(args, playlist_path):
|
|
|
254
255
|
new_media = set()
|
|
255
256
|
end_of_playlist = False
|
|
256
257
|
page_limit = args.backfill_pages or args.fixed_pages or args.max_pages
|
|
258
|
+
if args.recursive or args.webcache:
|
|
259
|
+
page_limit = 1
|
|
257
260
|
|
|
258
261
|
if args.confirm_ready:
|
|
259
262
|
if args.selenium:
|
|
@@ -283,8 +286,14 @@ def extractor(args, playlist_path):
|
|
|
283
286
|
page_known = set()
|
|
284
287
|
page_new = {}
|
|
285
288
|
try:
|
|
286
|
-
|
|
289
|
+
link_iter = (
|
|
290
|
+
extract_links.crawl(args, [page_path])
|
|
291
|
+
if args.recursive
|
|
292
|
+
else extract_links.iter_links(args, page_path)
|
|
293
|
+
)
|
|
294
|
+
for link_dict in link_iter:
|
|
287
295
|
link = link_dict.pop("link")
|
|
296
|
+
link_dict.pop("mime", None)
|
|
288
297
|
|
|
289
298
|
if link == args.stop_link:
|
|
290
299
|
end_of_playlist = True
|
|
@@ -302,7 +311,7 @@ def extractor(args, playlist_path):
|
|
|
302
311
|
printing.print_overwrite(f"Page {page_count} link scan: {len(page_new)} new [{len(page_known)} known]")
|
|
303
312
|
print(file=sys.stderr)
|
|
304
313
|
|
|
305
|
-
if not (args.backfill_pages or args.fixed_pages):
|
|
314
|
+
if not args.recursive and not (args.backfill_pages or args.fixed_pages):
|
|
306
315
|
if (args.stop_known and len(page_known) > args.stop_known) or (
|
|
307
316
|
args.stop_new and args.stop_new >= len(page_new)
|
|
308
317
|
):
|