library 3.2.3__tar.gz → 3.2.4__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.
Files changed (159) hide show
  1. {library-3.2.3 → library-3.2.4}/.github/README.md +1 -1
  2. {library-3.2.3 → library-3.2.4}/PKG-INFO +2 -2
  3. {library-3.2.3 → library-3.2.4}/library/__main__.py +1 -1
  4. {library-3.2.3 → library-3.2.4}/library/mediafiles/torrents_start.py +10 -5
  5. {library-3.2.3 → library-3.2.4}/library/utils/web.py +45 -8
  6. {library-3.2.3 → library-3.2.4}/pyproject.toml +1 -1
  7. {library-3.2.3 → library-3.2.4}/LICENSE +0 -0
  8. {library-3.2.3 → library-3.2.4}/library/__init__.py +0 -0
  9. {library-3.2.3 → library-3.2.4}/library/assets/__init__.py +0 -0
  10. {library-3.2.3 → library-3.2.4}/library/assets/calibre.css +0 -0
  11. {library-3.2.3 → library-3.2.4}/library/assets/kotobago.png +0 -0
  12. {library-3.2.3 → library-3.2.4}/library/createdb/__init__.py +0 -0
  13. {library-3.2.3 → library-3.2.4}/library/createdb/av.py +0 -0
  14. {library-3.2.3 → library-3.2.4}/library/createdb/computer_info.py +0 -0
  15. {library-3.2.3 → library-3.2.4}/library/createdb/computers_add.py +0 -0
  16. {library-3.2.3 → library-3.2.4}/library/createdb/fs_add.py +0 -0
  17. {library-3.2.3 → library-3.2.4}/library/createdb/fs_add_metadata.py +0 -0
  18. {library-3.2.3 → library-3.2.4}/library/createdb/gallery_add.py +0 -0
  19. {library-3.2.3 → library-3.2.4}/library/createdb/gallery_backend.py +0 -0
  20. {library-3.2.3 → library-3.2.4}/library/createdb/getty_add.py +0 -0
  21. {library-3.2.3 → library-3.2.4}/library/createdb/hn_add.py +0 -0
  22. {library-3.2.3 → library-3.2.4}/library/createdb/links_add.py +0 -0
  23. {library-3.2.3 → library-3.2.4}/library/createdb/nicotine_import.py +0 -0
  24. {library-3.2.3 → library-3.2.4}/library/createdb/places_import.py +0 -0
  25. {library-3.2.3 → library-3.2.4}/library/createdb/reddit_add.py +0 -0
  26. {library-3.2.3 → library-3.2.4}/library/createdb/row_add.py +0 -0
  27. {library-3.2.3 → library-3.2.4}/library/createdb/site_add.py +0 -0
  28. {library-3.2.3 → library-3.2.4}/library/createdb/substack.py +0 -0
  29. {library-3.2.3 → library-3.2.4}/library/createdb/subtitle.py +0 -0
  30. {library-3.2.3 → library-3.2.4}/library/createdb/tables_add.py +0 -0
  31. {library-3.2.3 → library-3.2.4}/library/createdb/tabs_add.py +0 -0
  32. {library-3.2.3 → library-3.2.4}/library/createdb/tildes.py +0 -0
  33. {library-3.2.3 → library-3.2.4}/library/createdb/torrents_add.py +0 -0
  34. {library-3.2.3 → library-3.2.4}/library/createdb/tube_add.py +0 -0
  35. {library-3.2.3 → library-3.2.4}/library/createdb/tube_backend.py +0 -0
  36. {library-3.2.3 → library-3.2.4}/library/createdb/web_add.py +0 -0
  37. {library-3.2.3 → library-3.2.4}/library/data/__init__.py +0 -0
  38. {library-3.2.3 → library-3.2.4}/library/data/dictionary.pkl +0 -0
  39. {library-3.2.3 → library-3.2.4}/library/data/ffmpeg_errors.py +0 -0
  40. {library-3.2.3 → library-3.2.4}/library/data/http_errors.py +0 -0
  41. {library-3.2.3 → library-3.2.4}/library/data/imagemagick_errors.py +0 -0
  42. {library-3.2.3 → library-3.2.4}/library/data/unar_errors.py +0 -0
  43. {library-3.2.3 → library-3.2.4}/library/data/wordbank.py +0 -0
  44. {library-3.2.3 → library-3.2.4}/library/data/yt_dlp_errors.py +0 -0
  45. {library-3.2.3 → library-3.2.4}/library/editdb/__init__.py +0 -0
  46. {library-3.2.3 → library-3.2.4}/library/editdb/dedupe_db.py +0 -0
  47. {library-3.2.3 → library-3.2.4}/library/editdb/dedupe_media.py +0 -0
  48. {library-3.2.3 → library-3.2.4}/library/editdb/merge_online_local.py +0 -0
  49. {library-3.2.3 → library-3.2.4}/library/editdb/mpv_watchlater.py +0 -0
  50. {library-3.2.3 → library-3.2.4}/library/editdb/pushshift.py +0 -0
  51. {library-3.2.3 → library-3.2.4}/library/editdb/reddit_selftext.py +0 -0
  52. {library-3.2.3 → library-3.2.4}/library/files/__init__.py +0 -0
  53. {library-3.2.3 → library-3.2.4}/library/files/christen.py +0 -0
  54. {library-3.2.3 → library-3.2.4}/library/files/sample_compare.py +0 -0
  55. {library-3.2.3 → library-3.2.4}/library/files/sample_hash.py +0 -0
  56. {library-3.2.3 → library-3.2.4}/library/files/similar_files.py +0 -0
  57. {library-3.2.3 → library-3.2.4}/library/folders/__init__.py +0 -0
  58. {library-3.2.3 → library-3.2.4}/library/folders/big_dirs.py +0 -0
  59. {library-3.2.3 → library-3.2.4}/library/folders/filter_src.py +0 -0
  60. {library-3.2.3 → library-3.2.4}/library/folders/merge_mv.py +0 -0
  61. {library-3.2.3 → library-3.2.4}/library/folders/mergerfs_cp.py +0 -0
  62. {library-3.2.3 → library-3.2.4}/library/folders/mount_stats.py +0 -0
  63. {library-3.2.3 → library-3.2.4}/library/folders/move_list.py +0 -0
  64. {library-3.2.3 → library-3.2.4}/library/folders/scatter.py +0 -0
  65. {library-3.2.3 → library-3.2.4}/library/folders/similar_folders.py +0 -0
  66. {library-3.2.3 → library-3.2.4}/library/fsdb/__init__.py +0 -0
  67. {library-3.2.3 → library-3.2.4}/library/fsdb/disk_usage.py +0 -0
  68. {library-3.2.3 → library-3.2.4}/library/fsdb/filesystem.py +0 -0
  69. {library-3.2.3 → library-3.2.4}/library/fsdb/folder_stats.py +0 -0
  70. {library-3.2.3 → library-3.2.4}/library/fsdb/search_db.py +0 -0
  71. {library-3.2.3 → library-3.2.4}/library/lb.py +0 -0
  72. {library-3.2.3 → library-3.2.4}/library/mediadb/__init__.py +0 -0
  73. {library-3.2.3 → library-3.2.4}/library/mediadb/block.py +0 -0
  74. {library-3.2.3 → library-3.2.4}/library/mediadb/db_history.py +0 -0
  75. {library-3.2.3 → library-3.2.4}/library/mediadb/db_media.py +0 -0
  76. {library-3.2.3 → library-3.2.4}/library/mediadb/db_playlists.py +0 -0
  77. {library-3.2.3 → library-3.2.4}/library/mediadb/download.py +0 -0
  78. {library-3.2.3 → library-3.2.4}/library/mediadb/download_status.py +0 -0
  79. {library-3.2.3 → library-3.2.4}/library/mediadb/history.py +0 -0
  80. {library-3.2.3 → library-3.2.4}/library/mediadb/history_add.py +0 -0
  81. {library-3.2.3 → library-3.2.4}/library/mediadb/optimize_db.py +0 -0
  82. {library-3.2.3 → library-3.2.4}/library/mediadb/playlists.py +0 -0
  83. {library-3.2.3 → library-3.2.4}/library/mediadb/redownload.py +0 -0
  84. {library-3.2.3 → library-3.2.4}/library/mediadb/search.py +0 -0
  85. {library-3.2.3 → library-3.2.4}/library/mediadb/stats.py +0 -0
  86. {library-3.2.3 → library-3.2.4}/library/mediafiles/__init__.py +0 -0
  87. {library-3.2.3 → library-3.2.4}/library/mediafiles/images_to_pdf.py +0 -0
  88. {library-3.2.3 → library-3.2.4}/library/mediafiles/media_check.py +0 -0
  89. {library-3.2.3 → library-3.2.4}/library/mediafiles/pdf_edit.py +0 -0
  90. {library-3.2.3 → library-3.2.4}/library/mediafiles/process_ffmpeg.py +0 -0
  91. {library-3.2.3 → library-3.2.4}/library/mediafiles/process_image.py +0 -0
  92. {library-3.2.3 → library-3.2.4}/library/mediafiles/process_media.py +0 -0
  93. {library-3.2.3 → library-3.2.4}/library/mediafiles/process_text.py +0 -0
  94. {library-3.2.3 → library-3.2.4}/library/mediafiles/torrents_dump.py +0 -0
  95. {library-3.2.3 → library-3.2.4}/library/mediafiles/unardel.py +0 -0
  96. {library-3.2.3 → library-3.2.4}/library/misc/__init__.py +0 -0
  97. {library-3.2.3 → library-3.2.4}/library/misc/dedupe_czkawka.py +0 -0
  98. {library-3.2.3 → library-3.2.4}/library/misc/export_text.py +0 -0
  99. {library-3.2.3 → library-3.2.4}/library/misc/search_help.py +0 -0
  100. {library-3.2.3 → library-3.2.4}/library/multidb/__init__.py +0 -0
  101. {library-3.2.3 → library-3.2.4}/library/multidb/allocate_torrents.py +0 -0
  102. {library-3.2.3 → library-3.2.4}/library/multidb/copy_play_counts.py +0 -0
  103. {library-3.2.3 → library-3.2.4}/library/multidb/merge_dbs.py +0 -0
  104. {library-3.2.3 → library-3.2.4}/library/playback/__init__.py +0 -0
  105. {library-3.2.3 → library-3.2.4}/library/playback/links_open.py +0 -0
  106. {library-3.2.3 → library-3.2.4}/library/playback/media_player.py +0 -0
  107. {library-3.2.3 → library-3.2.4}/library/playback/media_printer.py +0 -0
  108. {library-3.2.3 → library-3.2.4}/library/playback/play_actions.py +0 -0
  109. {library-3.2.3 → library-3.2.4}/library/playback/playback_control.py +0 -0
  110. {library-3.2.3 → library-3.2.4}/library/playback/post_actions.py +0 -0
  111. {library-3.2.3 → library-3.2.4}/library/playback/surf.py +0 -0
  112. {library-3.2.3 → library-3.2.4}/library/playback/tabs_open.py +0 -0
  113. {library-3.2.3 → library-3.2.4}/library/playback/torrents_info.py +0 -0
  114. {library-3.2.3 → library-3.2.4}/library/playback/torrents_remaining.py +0 -0
  115. {library-3.2.3 → library-3.2.4}/library/readme.py +0 -0
  116. {library-3.2.3 → library-3.2.4}/library/tablefiles/__init__.py +0 -0
  117. {library-3.2.3 → library-3.2.4}/library/tablefiles/columns.py +0 -0
  118. {library-3.2.3 → library-3.2.4}/library/tablefiles/eda.py +0 -0
  119. {library-3.2.3 → library-3.2.4}/library/tablefiles/incremental_diff.py +0 -0
  120. {library-3.2.3 → library-3.2.4}/library/tablefiles/markdown_tables.py +0 -0
  121. {library-3.2.3 → library-3.2.4}/library/tablefiles/mcda.py +0 -0
  122. {library-3.2.3 → library-3.2.4}/library/tablefiles/plot.py +0 -0
  123. {library-3.2.3 → library-3.2.4}/library/text/__init__.py +0 -0
  124. {library-3.2.3 → library-3.2.4}/library/text/cluster_sort.py +0 -0
  125. {library-3.2.3 → library-3.2.4}/library/text/combinations.py +0 -0
  126. {library-3.2.3 → library-3.2.4}/library/text/expand_links.py +0 -0
  127. {library-3.2.3 → library-3.2.4}/library/text/extract_links.py +0 -0
  128. {library-3.2.3 → library-3.2.4}/library/text/extract_text.py +0 -0
  129. {library-3.2.3 → library-3.2.4}/library/text/json_keys_rename.py +0 -0
  130. {library-3.2.3 → library-3.2.4}/library/text/markdown_links.py +0 -0
  131. {library-3.2.3 → library-3.2.4}/library/text/nouns.py +0 -0
  132. {library-3.2.3 → library-3.2.4}/library/text/regex_sort.py +0 -0
  133. {library-3.2.3 → library-3.2.4}/library/text/timestamps.py +0 -0
  134. {library-3.2.3 → library-3.2.4}/library/usage.py +0 -0
  135. {library-3.2.3 → library-3.2.4}/library/utils/__init__.py +0 -0
  136. {library-3.2.3 → library-3.2.4}/library/utils/arg_utils.py +0 -0
  137. {library-3.2.3 → library-3.2.4}/library/utils/arggroups.py +0 -0
  138. {library-3.2.3 → library-3.2.4}/library/utils/argparse_utils.py +0 -0
  139. {library-3.2.3 → library-3.2.4}/library/utils/consts.py +0 -0
  140. {library-3.2.3 → library-3.2.4}/library/utils/date_utils.py +0 -0
  141. {library-3.2.3 → library-3.2.4}/library/utils/db_utils.py +0 -0
  142. {library-3.2.3 → library-3.2.4}/library/utils/devices.py +0 -0
  143. {library-3.2.3 → library-3.2.4}/library/utils/file_utils.py +0 -0
  144. {library-3.2.3 → library-3.2.4}/library/utils/filter_engine.py +0 -0
  145. {library-3.2.3 → library-3.2.4}/library/utils/gui.py +0 -0
  146. {library-3.2.3 → library-3.2.4}/library/utils/iterables.py +0 -0
  147. {library-3.2.3 → library-3.2.4}/library/utils/log_utils.py +0 -0
  148. {library-3.2.3 → library-3.2.4}/library/utils/mpv_utils.py +0 -0
  149. {library-3.2.3 → library-3.2.4}/library/utils/nums.py +0 -0
  150. {library-3.2.3 → library-3.2.4}/library/utils/objects.py +0 -0
  151. {library-3.2.3 → library-3.2.4}/library/utils/path_utils.py +0 -0
  152. {library-3.2.3 → library-3.2.4}/library/utils/pd_utils.py +0 -0
  153. {library-3.2.3 → library-3.2.4}/library/utils/printing.py +0 -0
  154. {library-3.2.3 → library-3.2.4}/library/utils/processes.py +0 -0
  155. {library-3.2.3 → library-3.2.4}/library/utils/remote_processes.py +0 -0
  156. {library-3.2.3 → library-3.2.4}/library/utils/shell_utils.py +0 -0
  157. {library-3.2.3 → library-3.2.4}/library/utils/sql_utils.py +0 -0
  158. {library-3.2.3 → library-3.2.4}/library/utils/sqlgroups.py +0 -0
  159. {library-3.2.3 → library-3.2.4}/library/utils/strings.py +0 -0
@@ -99,7 +99,7 @@ To stop playing press Ctrl+C in either the terminal or mpv
99
99
  <details><summary>List all subcommands</summary>
100
100
 
101
101
  $ library
102
- library (v3.2.003; 102 subcommands)
102
+ library (v3.2.004; 102 subcommands)
103
103
 
104
104
  Create database subcommands:
105
105
  ╭─────────────────┬──────────────────────────────────────────╮
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: library
3
- Version: 3.2.3
3
+ Version: 3.2.4
4
4
  Summary: xk media library
5
5
  Author-Email: Jacob Chapman <7908073+chapmanjacobd@users.noreply.github.com>
6
6
  License: BSD 3-Clause License
@@ -207,7 +207,7 @@ To stop playing press Ctrl+C in either the terminal or mpv
207
207
  <details><summary>List all subcommands</summary>
208
208
 
209
209
  $ library
210
- library (v3.2.003; 102 subcommands)
210
+ library (v3.2.004; 102 subcommands)
211
211
 
212
212
  Create database subcommands:
213
213
  ╭─────────────────┬──────────────────────────────────────────╮
@@ -5,7 +5,7 @@ from tabulate import tabulate
5
5
  from library.utils import argparse_utils, iterables
6
6
  from library.utils.log_utils import log
7
7
 
8
- __version__ = "3.2.003"
8
+ __version__ = "3.2.004"
9
9
 
10
10
  progs = {
11
11
  "Create database subcommands": {
@@ -1,5 +1,4 @@
1
- import getpass, logging, shutil, time
2
- from contextlib import suppress
1
+ import getpass, shutil, time
3
2
  from pathlib import Path
4
3
  from time import sleep
5
4
 
@@ -65,9 +64,15 @@ def start_qBittorrent(args):
65
64
  HTTPADAPTER_ARGS={"pool_connections": 32, "pool_maxsize": 32},
66
65
  )
67
66
 
68
- with suppress(Exception):
67
+ try:
69
68
  qbt_client.auth_log_in()
70
69
  return qbt_client
70
+ except qbittorrentapi.LoginFailed:
71
+ # qBittorrent may allow API access with WebUI authentication disabled.
72
+ if args.username is None and args.password is None:
73
+ return qbt_client
74
+ except (qbittorrentapi.APIConnectionError, ConnectionRefusedError):
75
+ pass
71
76
 
72
77
  if shutil.which("qbittorrent-nox"):
73
78
  username = getpass.getuser()
@@ -85,13 +90,13 @@ def start_qBittorrent(args):
85
90
  log.debug("qBittorrent web UI ready")
86
91
  break
87
92
  except qbittorrentapi.LoginFailed as excinfo:
88
- logging.warning("Authentication failed. Check your qBit settings, --username, and --password: %s", excinfo)
93
+ log.warning("Authentication failed. Check your qBit settings, --username, and --password: %s", excinfo)
89
94
  break # stop if authentication failing
90
95
  except (qbittorrentapi.APIConnectionError, ConnectionRefusedError):
91
96
  time.sleep(2)
92
97
  attempt += 1
93
98
  else:
94
- logging.error("Failed to connect to qBittorrent web UI")
99
+ log.error("Failed to connect to qBittorrent web UI")
95
100
  raise ConnectionError("qBittorrent web UI not available")
96
101
 
97
102
  return qbt_client
@@ -262,7 +262,7 @@ def get_browser_profile_path(browser_name, profile=None):
262
262
  browser_name = browser_name.lower()
263
263
 
264
264
  if browser_name == "firefox":
265
- profile_roots = list(_firefox_browser_dirs())
265
+ profile_roots = [root for root in _firefox_browser_dirs() if os.path.isfile(os.path.join(root, "profiles.ini"))]
266
266
  if not profile_roots:
267
267
  return None
268
268
  root = profile_roots[0]
@@ -270,6 +270,9 @@ def get_browser_profile_path(browser_name, profile=None):
270
270
  candidate = os.path.join(root, profile)
271
271
  if os.path.isdir(candidate):
272
272
  return candidate
273
+ default_profile = _firefox_default_profile(root)
274
+ if default_profile and os.path.isdir(os.path.join(root, default_profile)):
275
+ return os.path.join(root, default_profile)
273
276
  return root
274
277
 
275
278
  if browser_name in {"chrome", "chromium", "brave", "edge", "opera", "vivaldi", "whale"}:
@@ -277,22 +280,53 @@ def get_browser_profile_path(browser_name, profile=None):
277
280
  browser_dir = settings["browser_dir"]
278
281
  if not os.path.isdir(browser_dir):
279
282
  return None
280
- if profile:
281
- candidate = os.path.join(browser_dir, profile)
282
- if os.path.isdir(candidate):
283
- return candidate
284
- default_profile = os.path.join(browser_dir, "Default")
285
- if os.path.isdir(default_profile):
286
- return default_profile
283
+ # selenium passes this via --user-data-dir, which expects the data root;
284
+ # chrome selects its own last-used profile unless told otherwise
287
285
  return browser_dir
288
286
 
289
287
  return None
290
288
 
291
289
 
290
+ def _firefox_default_profile(root):
291
+ import configparser
292
+
293
+ def read_ini(ini_name):
294
+ ini_path = os.path.join(root, ini_name)
295
+ if not os.path.isfile(ini_path):
296
+ return None
297
+ parser = configparser.RawConfigParser()
298
+ try:
299
+ with open(ini_path, encoding="utf8") as f:
300
+ parser.read_file(f)
301
+ except (configparser.Error, OSError):
302
+ return None
303
+ return parser
304
+
305
+ installs = read_ini("installs.ini")
306
+ if installs:
307
+ for section in installs.sections():
308
+ if section.lower().startswith("install"):
309
+ default = installs.get(section, "Default", fallback=None)
310
+ if default and os.path.isdir(os.path.join(root, default)):
311
+ return default
312
+
313
+ profiles = read_ini("profiles.ini")
314
+ if not profiles:
315
+ return None
316
+ sections = [s for s in profiles.sections() if s.lower().startswith("profile")]
317
+ for section in sections:
318
+ if profiles.get(section, "Default", fallback="") == "1":
319
+ path = profiles.get(section, "Path", fallback=None)
320
+ if path and os.path.isdir(os.path.join(root, path)):
321
+ return path
322
+ return next((p for p in (profiles.get(s, "Path", fallback=None) for s in sections) if p), None)
323
+
324
+
292
325
  def load_selenium(args, wire=False):
293
326
  if getattr(args, "driver", False):
294
327
  return
295
328
 
329
+ _profile = None
296
330
  if not args.user_data_dir and getattr(args, "cookies_from_browser", None):
297
331
  from library.utils.web import parse_cookies_from_browser
298
332
 
@@ -300,6 +334,7 @@ def load_selenium(args, wire=False):
300
334
  resolved = get_browser_profile_path(browser_name, profile)
301
335
  if resolved:
302
336
  args.user_data_dir = resolved
337
+ _profile = profile
303
338
  log.info("Using browser profile: %s", resolved)
304
339
  if browser_name == "firefox" and not getattr(args, "chrome", False):
305
340
  args.firefox = True
@@ -368,6 +403,8 @@ def load_selenium(args, wire=False):
368
403
  options = Options()
369
404
  if args.user_data_dir:
370
405
  options.add_argument(f"--user-data-dir={args.user_data_dir}")
406
+ if _profile:
407
+ options.add_argument(f"--profile-directory={_profile}")
371
408
 
372
409
  options.add_experimental_option(
373
410
  "prefs",
@@ -35,7 +35,7 @@ dynamic = []
35
35
  name = "library"
36
36
  readme = ".github/README.md"
37
37
  requires-python = ">=3.12"
38
- version = "3.2.3"
38
+ version = "3.2.4"
39
39
 
40
40
  [project.license]
41
41
  file = "LICENSE"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes