ping / odmpy Goto Github PK
View Code? Open in Web Editor NEWA simple command line manager for OverDrive/Libby loans. Download your library loans from the command line.
License: GNU General Public License v3.0
A simple command line manager for OverDrive/Libby loans. Download your library loans from the command line.
License: GNU General Public License v3.0
FILE_PART_RE = re.compile(
r"(?P<part_name>{[A-F0-9\-]{36}}[^#]+)(#(?P<second_stamp>\d+))?$"
)
I recently received an issue on my repository which uses the same regex. The regex will not match with this:
"path": "{31984D68-AD8F-4EF1-B00C-4A595BADE0D1}Fmt425-Part01.mp3#275.253"
The timestamp does not appear to be an integer (275.253) and will make odmpy crash when using libby with --direct. The book in question is the book with id 114614. Downloading works fine without --direct.
When trying to download a particular odm file, it errors out on the cover art. An output folder is created, but nothing is downloaded as the process exits out after tripping up on the cover art download. The file does appear to be truly broken, but would be great if odmpy could catch and handle the error.
# odmpy dl BjrkanSagas-64.odm
Downloading "The Björkan Sagas" by "Harold R. Johnson" in 4 parts...
Traceback (most recent call last):
File "/usr/sbin/odmpy", line 33, in
sys.exit(load_entry_point('odmpy==0.4.8', 'console_scripts', 'odmpy')())
File "/usr/lib/python3.10/site-packages/odmpy/main.py", line 26, in main
run()
File "/usr/lib/python3.10/site-packages/odmpy/odm.py", line 508, in run
cover_res.raise_for_status()
File "/usr/lib/python3.10/site-packages/requests/models.py", line 960, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://images.contentreserve.com/ImageType-100/2016-1/%7B00000000-0000-0000-0000-000000000232%7DImg100.jpg
Running version 0.4.8 within an alpine docker, but also able to reproduce this on Windows. Please let me know if further info is needed, or a copy of the .odm file.
When using Libby IDs to download, and perhaps when using Libby in general, it would be nice to be able to insert the Libby ID into the book folder. Right now it appears that %(id) inserts the ODM ID instead, which is inconvenient when batch-downloading by Libby ID (since my script doesn't know the ODM ID in advance, it can't tell where the resulting folder will be created).
Workaround: the ODM ID looks like it's in the --exportloans file, so if that turns out to be true I can complexify my script to convert between the two. I'll see what I can figure out.
Some books contain leading whitespaces in the chapter names after merging. eg. The Invincible by Stanislaw Lem.
Command used
odmpy -v dl -c -m -j -k multipart.odm
Ouput
Added chap tag => ch13: 6:21:21.215000-6:50:08.522000 " Invincible (38:33)" to "./The Invincible - Stanislaw Lem/The Invincible - Stanislaw Lem.mp3"
ffprobe output
Chapter #0:12: start 22881.215000, end 24608.522000
Metadata:
title : Invincible (38:33)
After merging more than one file, the chapter computation is skewed my many seconds due to eyed3 incorrectly computing file length.
The issue occurs here:
https://github.com/ping/odmpy/blob/master/odmpy/odm.py#L370
In a few samples tested locally, .info.time_secs
outputs lengths longer than the actual file.
Some ODMs do not include a link to a cover image (they show up in the Overdrive application with a question mark image in place of the cover image). In ODMs of this sort, odmpy will crash due to a conditional that seems to test the possibility of a missing image, but which actually doesn't have any alternate behavior.
The one-line conditional shown below dereferences the pointer whether or not it's null.
Traceback (most recent call last):
File "/home/william/.local/bin/odmpy", line 8, in <module>
sys.exit(main())
File "/home/william/.local/lib/python3.6/site-packages/odmpy/__main__.py", line 26, in main
run()
File "/home/william/.local/lib/python3.6/site-packages/odmpy/odm.py", line 216, in run
cover_url = metadata.find('CoverUrl').text if metadata.find('CoverUrl') else metadata.find('CoverUrl').text
AttributeError: 'NoneType' object has no attribute 'text'
I am using AudioBookShelf to host audiobooks. it wants books that are series to be stored in the following folder format
.%AuthorName%%SeriesName%\Book %ReadingOrder% - %Title%\
having the ability to specify the ReadingOrder in the --bookfolderformat would be SUPER helpful!
Thanks much!
Snarf
It's not easy to get good metadata about audiobooks (Overdrive tags are terrible); would it be possible to save the metadata Overdrive/Libby provides in a durable form alongside the MP3s? I used to parse the ODM files, but many projects think they're being retired, and anyhow the libby interface of odmpy doesn't save them anymore.
My favorite format is OPF, but a json dump would be adequate.
I get the following backtrace when running odmpy on the attached ODM file; the cause is either the "
or the é
, confirmed by editing them both out, it loaded just fine.
Hm, not sure how to attach, I'll submit this and see if I can figure it out.
Traceback (most recent call last):
File "/home/william/.local/bin/odmpy", line 8, in <module>
sys.exit(main())
File "/home/william/.local/lib/python3.8/site-packages/odmpy/__main__.py", line 26, in main
run()
File "/home/william/.local/lib/python3.8/site-packages/odmpy/odm.py", line 231, in run
metadata = xml.etree.ElementTree.fromstring(
File "/usr/lib/python3.8/xml/etree/ElementTree.py", line 1320, in XML
parser.feed(text)
xml.etree.ElementTree.ParseError: undefined entity: line 1, column 1136
./fetchodm.sh: cannot odmpy dl -r 10 -k -d /mnt/hdd-8TB/sharing/downloads/pyodm-dl/tmp.H7nwXYVOpa /mnt/hdd-8TB/sharing/downloads/pyodm-dl/tmp.H7nwXYVOpa/SkylarkofSpace9781596078707.odm
Some books can only be opened with the Libby app (similar to magazines), would be awesome to have a way of downloading these.
No longer functional, due to changes on Libby.
Lots of script errors, but this URL seems to be part of the issue: Forbidden for url: https://sentry-read.svc.overdrive.com/chip/sync
odmpy immediately crashes when running any command. Please see command line output below. I wasn't able to resolve it by running pip3 uninstall odmpy
followed by pip3 install git+https://[email protected]/ping/odmpy.git --upgrade
$ odmpy
Traceback (most recent call last):
File "/opt/homebrew/bin/odmpy", line 5, in <module>
from odmpy.__main__ import main
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/__main__.py", line 21, in <module>
from .odm import run, LibbyNotConfiguredError
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/odm.py", line 42, in <module>
from .processing import (
ModuleNotFoundError: No module named 'odmpy.processing'
Traceback (most recent call last):
File "/home/zoidberg/.local/bin/odmpy", line 8, in
sys.exit(main())
File "/home/zoidberg/.local/lib/python3.8/site-packages/odmpy/main.py", line 26, in main
run()
File "/home/zoidberg/.local/lib/python3.8/site-packages/odmpy/odm.py", line 281, in run
os.makedirs(book_folder)
File "/usr/lib/python3.8/os.py", line 223, in makedirs
mkdir(name, mode)
OSError: [Errno 36] File name too long: "audiobooks/Orson Scott Card's Intergalactic Medicine Show - Orson Scott Card, Edmund R. Schubert, Wayne Wightman, Stefan Rudnicki, Gabrielle De Cuir, Roxanne Hernandez, Arthur Morey, Emily Janice Card, Paul Boehmer, Various Narrators, Claire Bloom, Susan Hanfield, Mary Robinette Kowal, Eric James Stone, Aliette de Bodard, Others"
On a new borrow getting 406 error with default odm file download.
Not sure if this is my library no longer allowing an odm file access or something else, but I thought I'd report it.
I had an old borrow in my loans, it worked, but both new borrows had this error.
NOTE: --direct worked fine
commit 5af3cac
An unexpected error has occured
Traceback (most recent call last):
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby.py", line 349, in make_request
res.raise_for_status()
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\requests\models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 406 Client Error: Not Acceptable for url: https://sentry-read.svc.overdrive.com/card/35351901/loan/74599/fulfill/LibbyFormats.AudioBookMP3
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\odm.py", line 1035, in run
extract_loan_file(libby_client, selected_loan, args),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\odm.py", line 358, in extract_loan_file
odm_res_content = libby_client.fulfill_loan_file(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby.py", line 683, in fulfill_loan_file
res: requests.Response = self.make_request(
^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby.py", line 358, in make_request
ErrorHandler.process(http_err)
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby_errors.py", line 103, in process
raise ClientError(
odmpy.libby_errors.ClientError: <odmpy.libby_errors.ClientError; http_status=406, msg='406 Client Error: Not Acceptable for url: https://sentry-read.svc.overdrive.com/card/35351901/loan/74599/fulfill/LibbyFormats.AudioBookMP3', error_response=' ''>
Traceback (most recent call last):
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby.py", line 349, in make_request
res.raise_for_status()
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\requests\models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 406 Client Error: Not Acceptable for url: https://sentry-read.svc.overdrive.com/card/35351901/loan/74599/fulfill/LibbyFormats.AudioBookMP3
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\__main__.py", line 34, in <module>
main()
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\__main__.py", line 26, in main
run()
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\odm.py", line 1035, in run
extract_loan_file(libby_client, selected_loan, args),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\odm.py", line 358, in extract_loan_file
odm_res_content = libby_client.fulfill_loan_file(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby.py", line 683, in fulfill_loan_file
res: requests.Response = self.make_request(
^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby.py", line 358, in make_request
ErrorHandler.process(http_err)
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby_errors.py", line 103, in process
raise ClientError(
odmpy.libby_errors.ClientError: <odmpy.libby_errors.ClientError; http_status=406, msg='406 Client Error: Not Acceptable for url: https://sentry-read.svc.overdrive.com/card/35351901/loan/74599/fulfill/LibbyFormats.AudioBookMP3', error_response=' ''>
I was wondering if it's possible to add an option to download multiple .odm at once
On https://github.com/ping/odmpy/releases/tag/0.8.0, I see a release titled "Release 0.80", but the git tag is 0.8.0, which makes me think it's really just a typo in the release name.
Can you add an --audiobooks switch or maybe --noaudio to just download ebooks/magazines? Thanks.
Hi, the tool works great although I'm trying to merge the existing downloaded mp3 files from the windows app into one m4b file with the chapters and cover. Is this possible? The goal is to take the existing book folder and combine it with the chapter and cover info into an m4b file. Thanks!
When using the options -m --mergeformat m4b
ffmpeg displays the following warning:
Multiple -c, -codec, -acodec, -vcodec, -scodec or -dcodec options specified for stream 0, only the last option '-c:a aac' will be used.
To get the tests to pass I had to update os.rename to os.replace
Pretty crazy difference between Windows and Unix behavior
On Windows, if dst exists a FileExistsError is always raised. The operation may fail if src and dst are on different filesystems. Use shutil.move() to support moves to a different filesystem.
On Unix, if src is a file and dst is a directory or vice-versa, an IsADirectoryError or a NotADirectoryError will be raised respectively. If both are directories and dst is empty, dst will be silently replaced. If dst is a non-empty directory, an OSError is raised. If both are files, dst will be replaced silently if the user has permission. The operation may fail on some Unix flavors if src and dst are on different filesystems. If successful, the renaming will be an atomic operation (this is a POSIX requirement).
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "C:\Users\nnn\Documents\dev\git\odmpy\odmpy\__main__.py", line 32, in <module>
main()
File "C:\Users\nnn\Documents\dev\git\odmpy\odmpy\__main__.py", line 26, in main
run()
File "C:\Users\nnn\Documents\dev\git\odmpy\odmpy\odm.py", line 764, in run
process_odm(args.odm_file, args, logger)
File "C:\Users\nnn\Documents\dev\git\odmpy\odmpy\processing.py", line 590, in process_odm
merge_into_mp3(
File "C:\Users\nnn\Documents\dev\git\odmpy\odmpy\shared.py", line 322, in merge_into_mp3
os.rename(temp_book_filename, book_filename)
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'tests/data/downloads/Ceremonies For Christmas - Robert Herrick\\Ceremonies For Christmas - Robert Herrick.mp3.part' -> 'tests/data/downloads/Ceremonies For Christmas - Robert Herrick\\Ceremonies For Christmas - Robert Herrick.mp3'
Describe the problem
When adding chapter markers to a book with very long chapters, duplicate markers are added with the suffix (00:00)
.
Chapters In Libby:
Chapters after extraction:
The book otherwise plays great, so this is fairly minor in the scheme of things.
To Reproduce
I noticed it with this version of Good Omens, but I think I've seen it other places too.
I ran:
odmpy libby --settings ~/.config/odmpy --latest 1 --downloaddir ~/Downloads/audiobooks --chapters --merge --mergeformat m4b --nobookfolder --bookfileformat "%(Author)s - %(Series)s %(ReadingOrder)s - %(Title)s"
Version/Environment
odmpy 0.8.1 [Python 3.11.4-darwin]
ffmpeg version 6.0 Copyright (c) 2000-2023 the FFmpeg developers
built with Apple clang version 14.0.3 (clang-1403.0.22.14.1)
Crash when title contains a / ( forward slash ) on win11 in version 0.6.7
I was able to get past this by downloading the odm and changing the / to a - and re-running.
Describe the problem
I've found that folder/file names which contain a ':' character cause issues on some filesystems. I wonder if it would be possible to provide a mechanism to escape/replace/remove that character (or certain characters) for folder/file names.
To Reproduce
Download an audio book with a ':' in the title.
Version/Environment
odmpy 0.7.7 [Python 3.8.10-linux]
I was hoping I could create multiple subfolders. The obvious example would be /author/title or even /author/series (if series exists)/title.
Current Head:
commit 0f769e71b25c3ce64917b52f195cc47401cdbe9d (HEAD -> master, ping/master)
Author: ping <[email protected]>
Date: Sat Feb 18 16:23:10 2023 +0800
======================================================================
ERROR: test_loans (tests.libby_tests.LibbyClientTests.test_loans)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\urllib3\connection.py", line 174, in _new_conn
conn = connection.create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\urllib3\util\connection.py", line 95, in create_connection
raise err
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\urllib3\util\connection.py", line 85, in create_connection
sock.connect(sa)
TimeoutError: timed out
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\urllib3\connectionpool.py", line 703, in urlopen
httplib_response = self._make_request(
^^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\urllib3\connectionpool.py", line 386, in _make_request
self._validate_conn(conn)
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\urllib3\connectionpool.py", line 1042, in _validate_conn
conn.connect()
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\urllib3\connection.py", line 358, in connect
self.sock = conn = self._new_conn()
^^^^^^^^^^^^^^^^
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\urllib3\connection.py", line 179, in _new_conn
raise ConnectTimeoutError(
urllib3.exceptions.ConnectTimeoutError: (<urllib3.connection.HTTPSConnection object at 0x000001C38FD14550>, 'Connection to sentry-read.svc.overdrive.com timed out. (connect timeout=10)')
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\requests\adapters.py", line 489, in send
resp = conn.urlopen(
^^^^^^^^^^^^^
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\urllib3\connectionpool.py", line 787, in urlopen
retries = retries.increment(
^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\urllib3\util\retry.py", line 592, in increment
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='sentry-read.svc.overdrive.com', port=443): Max retries exceeded with url: /chip/sync (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x000001C38FD14550>, 'Connection to sentry-read.svc.overdrive.com timed out. (connect timeout=10)'))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby.py", line 309, in make_request
res = session.send(
^^^^^^^^^^^^^
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\requests\sessions.py", line 701, in send
r = adapter.send(request, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\AppData\Roaming\Python\Python311\site-packages\requests\adapters.py", line 553, in send
raise ConnectTimeout(e, request=request)
requests.exceptions.ConnectTimeout: HTTPSConnectionPool(host='sentry-read.svc.overdrive.com', port=443): Max retries exceeded with url: /chip/sync (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x000001C38FD14550>, 'Connection to sentry-read.svc.overdrive.com timed out. (connect timeout=10)'))
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\nnn\Documents\dev\odmpy\tests\libby_tests.py", line 245, in test_loans
res = self.client.get_loans()
^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby.py", line 515, in get_loans
return self.sync().get("loans", [])
^^^^^^^^^^^
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby.py", line 409, in sync
res: Dict = self.make_request("chip/sync")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\nnn\Documents\dev\odmpy\odmpy\libby.py", line 321, in make_request
raise ClientConnectionError(str(conn_err)) from conn_err
odmpy.libby_errors.ClientConnectionError: <odmpy.libby_errors.ClientConnectionError; http_status=0, msg='HTTPSConnectionPool(host='sentry-read.svc.overdrive.com', port=443): Max retries exceeded with url: /chip/sync (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x000001C38FD14550>, 'Connection to sentry-read.svc.overdrive.com timed out. (connect timeout=10)'))', error_response='''>
I noticed that the book covers in the library appear stretched in the previews and when you download them, but appear in the correct aspect ratio (1:1) in the web player.
Update: I realized we could resize the cover with ffmpeg and not create a new dependency. 510x510px seems reasonable since the original image is 510px wide and there isn't any gain in scaling it up. Declaring a specific quality seems necessary, otherwise the resulting image is extremely compressed.
ffmpeg -y -i cover.jpg -vf scale=510:510 -qmin 1 -qscale:v 1 cover.jpg
Most players expect the embedded art to be square (like it would be in a regular music file). It is an easy fix but depends on adding the Python Image Library to resize the cover.
from PIL import Image
img = Image.open('cover.jpg')
img = img.resize(((img.size[0]),(img.size[0])), Image.LANCZOS)
img.save('cover.jpg')
Would you be interested in merging this and resizing all covers by default?
Or maybe making it a new argument? eg. -r "Resize cover image to 1:1 aspect ratio"
Using the --merge command to merge the .mp3s causes issues when trying to seek to an exact time on many platforms.
Here:
https://github.com/ping/odmpy/blob/master/odmpy/odm.py#L486
You are using ffmpeg to concatenate the .mp3s.
The original .mp3s are CBR 64kbps. However, when ffmpeg concatenates .mp3s, it turns them into VBR.
Here is an article explaining this issue in more detail:
https://marco.org/2016/08/15/vbr-mp3-plea
What you really mean to do is concatenate the CBR streams into a CBR output. That output file will be easily seekable. Here is one library that does that:
https://darrenmulholland.com/dev/mp3cat.html
I recommend using that library to concatenate the mp3s instead of ffmpeg.
When trying to create a merged m4b file with the options
odmpy -v dl -c -m --mergeformat m4b -k -f file.odm
ffmpeg fails because it can't use the embedded cover art
[mp4 @ 0x7fc62a802e00] Could not find tag for codec h264 in stream #0, codec not currently supported in container
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
Error initializing output stream 0:1 --
[aac @ 0x7fc62a805e00] Qavg: nan
Conversion failed!
ffmpeg exited with the code: 1
ffmpeg -version output
ffmpeg version 4.3.1 Copyright (c) 2000-2020 the FFmpeg developers
built with Apple clang version 11.0.0 (clang-1100.0.33.17)
Download. Choose from 1-5 (separate choices with a space or leave blank to quit),
then press enter: 4
Opening ebook "Physics for Game Developers"...
Downloading toc.ncx: 100%|███████████████████████████████████████████████████████████| 274/274 [01:28<00:00, 3.09it/s]
An unexpected error has occurred
Traceback (most recent call last):
File "C:\Users\titus\AppData\Local\Programs\Python\Python311\Lib\site-packages\odmpy\odm.py", line 1079, in run
extract_loan_file(libby_client, selected_loan, args)
File "C:\Users\titus\AppData\Local\Programs\Python\Python311\Lib\site-packages\odmpy\odm.py", line 366, in extract_loan_file
process_ebook_loan(
File "C:\Users\titus\AppData\Local\Programs\Python\Python311\Lib\site-packages\odmpy\processing\ebook.py", line 664, in process_ebook_loan
ncx_soup = BeautifulSoup(ncx_f, features="xml")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\titus\AppData\Local\Programs\Python\Python311\Lib\site-packages\bs4_init_.py", line 250, in init
raise FeatureNotFound(
bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: xml. Do you need to install a parser library?
Traceback (most recent call last):
File "C:\Users\titus\AppData\Local\Programs\Python\Python311\Scripts\odmpy-script.py", line 33, in
sys.exit(load_entry_point('odmpy==0.7.6', 'console_scripts', 'odmpy')())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\titus\AppData\Local\Programs\Python\Python311\Lib\site-packages\odmpy_main_.py", line 27, in main
run()
File "C:\Users\titus\AppData\Local\Programs\Python\Python311\Lib\site-packages\odmpy\odm.py", line 1079, in run
extract_loan_file(libby_client, selected_loan, args)
File "C:\Users\titus\AppData\Local\Programs\Python\Python311\Lib\site-packages\odmpy\odm.py", line 366, in extract_loan_file
process_ebook_loan(
File "C:\Users\titus\AppData\Local\Programs\Python\Python311\Lib\site-packages\odmpy\processing\ebook.py", line 664, in process_ebook_loan
ncx_soup = BeautifulSoup(ncx_f, features="xml")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\titus\AppData\Local\Programs\Python\Python311\Lib\site-packages\bs4_init_.py", line 250, in init
raise FeatureNotFound(
bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: xml. Do you need to install a parser library?
The Problem
I'm receiving the following error message:
odmpy.libby_errors.ClientError: <odmpy.libby_errors.ClientError; http_status=403, msg='403 Client Error: Forbidden for url: https://sentry-read.svc.overdrive.com/chip/sync', error_response='{"result":"missing_chip"}''>
Once I get the error message, odmpy stops, and I'm unable to do anything with it 😕
To Reproduce
Using the base command of odmpy libby
Version/Environment
odmpy 0.8.1 [Python 3.11.5-darwin]
I'd like to be able to integrate odmpy with my library a bit more, so I don't have to log in to get my books onto my server. But rather than suggesting something complex like automated downloads of all files (like Overdrive and Libby do), I'd like to go a bit simpler, closer to the current design.
I can use the json export odmpy libby --exportloans
to get the IDs of all titles, exclude the ones I have already, and thereby get the IDs I need. But how do I ask Libby to download them? Can I ask for a feature to pass the Libby ID (stored as the top-level JSON "id" in each book) into pyodm? Or is there some way to find the download number you're supposed to pass to pyodm libby --select
(without having to parse titles out of the human-readable list)?
Describe the problem
This week odmpy started failing on processing every audiobook. It successfully downloads all the parts but on the transcode to M4B errors when parsing the date field. I'm going to try debugging more, but submitting this issue in case anyone is already aware of a solution. Traceback logs below.
To Reproduce
odmpy libby \
--direct \
--latest 1 \
--downloaddir=<downloaddir> \
--settings=<settingsdir> \
--keepcover \
--chapters \
--merge \
--mergeformat=m4b \
--mergecodec=aac \
--removefrompaths ":," \
--bookfolderformat "%(Author)s/%(Title)s" \
--bookfileformat "%(Author)s - %(Title)s"
Version/Environment
odmpy 0.8.1 [Python 3.11.6-darwin]
Traceback log
odmpy Interactive Client for Libby
----------------------------------------------------------------------
Non-interactive mode. Downloading latest 1 loan...
Opening audiobook "<book title>"...
Downloading "<book title>" by "<book author>" in 19 parts...
...
Already saved /Users/server/Music/Audiobooks/.....part-19.mp3
Generating "/Users/server/Music/Audiobooks/......"...
size= 457164kB time=16:15:16.88 bitrate= 64.0kbits/s speed=6.29e+03x
An unexpected error has occurred
Traceback (most recent call last):
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/odm.py", line 953, in run
process_audiobook_loan(
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/processing/audiobook.py", line 362, in process_audiobook_loan
write_tags(
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/processing/shared.py", line 250, in write_tags
audiofile.tag.release_date = published_date
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/eyed3/id3/tag.py", line 506, in _setReleaseDate
self._setDate(b"TDRL", date)
File "/opt/homebrew/lib/python3.11/site-packages/eyed3/id3/tag.py", line 649, in _setDate
date = core.Date.parse(date)
^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/eyed3/core.py", line 380, in parse
pdate, fmt = Date._validateFormat(s)
^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/eyed3/core.py", line 368, in _validateFormat
raise ValueError(f"Invalid date string: {s}")
ValueError: Invalid date string: 2021-02-16T05:00:00+00:00
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/__main__.py", line 35, in <module>
main()
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/__main__.py", line 27, in main
run()
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/odm.py", line 953, in run
process_audiobook_loan(
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/processing/audiobook.py", line 362, in process_audiobook_loan
write_tags(
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/processing/shared.py", line 250, in write_tags
audiofile.tag.release_date = published_date
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/eyed3/id3/tag.py", line 506, in _setReleaseDate
self._setDate(b"TDRL", date)
File "/opt/homebrew/lib/python3.11/site-packages/eyed3/id3/tag.py", line 649, in _setDate
date = core.Date.parse(date)
^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/eyed3/core.py", line 380, in parse
pdate, fmt = Date._validateFormat(s)
^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/eyed3/core.py", line 368, in _validateFormat
raise ValueError(f"Invalid date string: {s}")
ValueError: Invalid date string: 2021-02-16T05:00:00+00:00
Using odm libby now produces this
An unexpected error has occurred
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/odmpy/libby.py", line 357, in make_request
res.raise_for_status()
File "/usr/local/lib/python3.10/dist-packages/requests/models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://sentry-read.svc.overdrive.com/chip/sync
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/odmpy/odm.py", line 846, in run
synced_state = libby_client.sync()
File "/usr/local/lib/python3.10/dist-packages/odmpy/libby.py", line 457, in sync
res: Dict = self.make_request("chip/sync") File "/usr/local/lib/python3.10/dist-packages/odmpy/libby.py", line 366, in make_request
ErrorHandler.process(http_err)
File "/usr/local/lib/python3.10/dist-packages/odmpy/libby_errors.py", line 103, in process raise ClientError(
odmpy.libby_errors.ClientError: <odmpy.libby_errors.ClientError; http_status=403, msg='403 Client Error: Forbidden for url: https://sentry-read.svc.overdrive.com/chip/sync', error_response='{"result":"missing_chip"}''>
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/odmpy/libby.py", line 357, in make_request
res.raise_for_status()
File "/usr/local/lib/python3.10/dist-packages/requests/models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://sentry-read.svc.overdrive.com/chip/sync
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/bin/odmpy", line 8, in
sys.exit(main())
File "/usr/local/lib/python3.10/dist-packages/odmpy/main.py", line 27, in main
run()
File "/usr/local/lib/python3.10/dist-packages/odmpy/odm.py", line 846, in run
synced_state = libby_client.sync()
File "/usr/local/lib/python3.10/dist-packages/odmpy/libby.py", line 457, in sync
res: Dict = self.make_request("chip/sync") File "/usr/local/lib/python3.10/dist-packages/odmpy/libby.py", line 366, in make_request
ErrorHandler.process(http_err)
File "/usr/local/lib/python3.10/dist-packages/odmpy/libby_errors.py", line 103, in process raise ClientError(
odmpy.libby_errors.ClientError: <odmpy.libby_errors.ClientError; http_status=403, msg='403 Client Error: Forbidden for url: https://sentry-read.svc.overdrive.com/chip/sync', error_response='{"result":"missing_chip"}''>
Installed following the install from source pip instructions, it was working perfectly 24 hours ago.
The ffmpeg command sometimes reads from stdin even when it isn't asked to. The result is that odmpy will appear to produce strange output about failure to parse debug commands (and it's entirely possible that in some cases stdin will contain some valid debug command that could really mess things up).
In my case, I called odmpy from inside a bash while loop on "ls *.odm | while read line ...", and because ffmpeg was eating stdin, the while loop would only process the first successful file.
This can be resolved by always running ffmpeg with the -nostdin
option, or by always running with redirection from /dev/null.
See also https://superuser.com/questions/1492507/why-does-ffmpeg-require-nostdin-in-while-loop
Describe the problem
I'd like to be able to run this program in a background job to periodically check for new books and automatically download them. the --latest N
command sort of does that because it will recognize already downloaded books and not redownload them. however it would be great if there was a command like --new
which compares all the available books with what exists locally and then downloads any books that were not currently downloaded.
Describe the problem
Sometimes I will have the following error on download:
Some personal data redacted.
I think this might have to do with when the book is close to return, odmpy is still trying to download a book which might had been returned?
Also when this happen, this will fail completely. Is there a way to not fail completely, instead will continue to download the next title instead? Thanks
An unexpected error has occurred
Traceback (most recent call last):
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby.py", line 358, in make_request
res.raise_for_status()
File "/home/joshua/.local/lib/python3.9/site-packages/requests/models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://sentry-read.svc.overdrive.com/open/book/card/1234/title/1234
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/odm.py", line 952, in run
extract_bundled_contents(
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/odm.py", line 327, in extract_bundled_contents
extract_loan_file(libby_client, bundled_media, args)
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/odm.py", line 375, in extract_loan_file
_, openbook, rosters = libby_client.process_ebook(selected_loan)
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby.py", line 822, in process_ebook
download_base, meta = self.prepare_loan(loan)
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby.py", line 786, in prepare_loan
meta = self.open_loan(loan_type, card_id, title_id)
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby.py", line 767, in open_loan
res: Dict = self.make_request(
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby.py", line 367, in make_request
ErrorHandler.process(http_err)
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby_errors.py", line 103, in process
raise ClientError(
odmpy.libby_errors.ClientError: <odmpy.libby_errors.ClientError; http_status=404, msg='404 Client Error: Not Found for url: https://sentry-read.svc.overdrive.com/open/book/card/64855467/title/984832', error_response='{"result":"upstream_failure","upstream":{"errorCode":"PatronDoesNotHaveTitleCheckedOut","service":"THUNDER","httpStatus":404,"userExplanation":"Patron does not have title checked out.","correlationId":"d37redactede"}}''>
Traceback (most recent call last):
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby.py", line 358, in make_request
res.raise_for_status()
File "/home/joshua/.local/lib/python3.9/site-packages/requests/models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://sentry-read.svc.overdrive.com/open/book/card/1234/title/1234
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/joshua/.local/bin/odmpy", line 8, in <module>
sys.exit(main())
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/__main__.py", line 27, in main
run()
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/odm.py", line 952, in run
extract_bundled_contents(
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/odm.py", line 327, in extract_bundled_contents
extract_loan_file(libby_client, bundled_media, args)
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/odm.py", line 375, in extract_loan_file
_, openbook, rosters = libby_client.process_ebook(selected_loan)
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby.py", line 822, in process_ebook
download_base, meta = self.prepare_loan(loan)
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby.py", line 786, in prepare_loan
meta = self.open_loan(loan_type, card_id, title_id)
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby.py", line 767, in open_loan
res: Dict = self.make_request(
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby.py", line 367, in make_request
ErrorHandler.process(http_err)
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/libby_errors.py", line 103, in process
raise ClientError(
odmpy.libby_errors.ClientError: <odmpy.libby_errors.ClientError; http_status=404, msg='404 Client Error: Not Found for url: https://sentry-read.svc.overdrive.com/open/book/card/1234/title/1234', error_response='{"result":"upstream_failure","upstream":{"errorCode":"PatronDoesNotHaveTitleCheckedOut","service":"THUNDER","httpStatus":404,"userExplanation":"Patron does not have title checked out.","correlationId":"d37redactede"}}''>
To Reproduce
odmpy libby -c -k -d Folder/ --opf --direct --latest 99 --bookfolderformat "%(Title)s - %(Author)s - %(ID)s" --setting setting_folder/
Version/Environment
odmpy 0.8.0 [Python 3.9.2-linux]
it seems that pip3 no longer works after install of pipx
uninstalling pipx doesnt help, also my python version is 3.11, some writers on the internet claim that pipx is required
for new ubuntu
should i give up on odmpy for a while? is there an another way to add missing python libraries?
sorry to bother you, im really impressed by your work. but this old hardware engineer can't seem to work problems of this complexity,
to be really clear its not your script its some python3 pip pipx changes.
thank you for any suggestions
bob
.
A clear and concise description of what the bug/error is. If there is an error traceback dump, paste the text here (please avoid screenshots).
To Reproduce
Please include the full command used, for example odmpy libby --direct
Version/Environment
Please paste the contents of odmpy --version
here.
Describe the problem
I logged in via code for the first time today. When I ran odmpy libby
, it shows the one audiobook I have. When type 1 and hit enter, the download begin but it errors out with following output:
Downloading "Visual Thinking" by "Temple Grandin, Ph.D." in 14 parts...
b'<LicenseError xmlns="http://license.overdrive.com/2008/03/LicenseError.xsd" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ErrorCode>1002</ErrorCode><ErrorMessage>Hash Mismatch</ErrorMessage><ErrorDetails i:nil="true"/></LicenseError>'
Error: HTTP Error while downloading license.
To Reproduce
odmpy libby
Version/Environment
odmpy 0.8.1 [Python 3.10.12-linux]
Describe the problem
Intermittenly, odmpy libby has the following error:
It shows up sometimes, but fine when I rerun it.
Traceback (most recent call last):
File "/home/joshua/.local/bin/odmpy", line 8, in <module>
An unexpected error has occurred
Traceback (most recent call last):
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/odm.py", line 1005, in run
expiry_date = parse_datetime(loan["expireDate"])
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/utils.py", line 67, in parse_datetime
dt = datetime.strptime(value, fmt)
File "/usr/lib/python3.9/_strptime.py", line 568, in _strptime_datetime
tt, fraction, gmtoff_fraction = _strptime(data_string, format)
: sys.exit(main())
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/__main__.py", line 27, in main
run()
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/odm.py", line 1005, in run
expiry_date = parse_datetime(loan["expireDate"])
File "/home/joshua/.local/lib/python3.9/site-packages/odmpy/utils.py", line 67, in parse_datetime
dt = datetime.strptime(value, fmt)
File "/usr/lib/python3.9/_strptime.py", line 568, in _strptime_datetime
tt, fraction, gmtoff_fraction = _strptime(data_string, format)
File "/usr/lib/python3.9/_strptime.py", line 349, in _strptime
raise ValueError("time data %r does not match format %r" %
ValueError: time data '2023-09-14T07:20:30+00:00' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'
To Reproduce
Please include the full command used, for example odmpy libby
Version/Environment
odmpy 0.8.0 [Python 3.9.2-linux]
I just got a TCP disconnect in the middle of a download; I tried and failed to find a way to resume it. It looks like there's some mechanism for using the license file to resume the download ... but if so, what might it take to actually do it? (For now, of course, I just re-download the ODM file.)
odmpy crashes when trying to download an audiobook with the libby command. I've included the command and crash output below. I was able to revert to odmpy-0.8.0 and execute the same command without this issue.
Relevant command line information
Base command odmpy libby -m -c --nobookfolder --ebooks --direct --settings ~/.odmpy/
Resulting output (with intermediate audiobook selection)
odmpy Interactive Client for Libby
----------------------------------------------------------------------
Found 2 loans.
1: Homeward Bound 🎧 Elaine Tyler May
* Expires: 2023-10-25 REDACTED
2: Dealing with China 🎧 Henry M. Paulson Jr.
* Expires: 2023-10-25 REDACTED
Download. Choose from 1-2 (separate choices with a space or leave blank to quit),
then press enter: 1 2
Opening audiobook "Homeward Bound"...
An unexpected error has occurred
Traceback (most recent call last):
File "/opt/homebrew/lib/python3.11/site-packages/requests/models.py", line 971, in json
return complexjson.loads(self.text, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/odm.py", line 1175, in run
openbook, toc = libby_client.process_audiobook(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/libby.py", line 835, in process_audiobook
download_base, meta = self.prepare_loan(loan)
^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/libby.py", line 817, in prepare_loan
_ = self.make_request(
^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/libby.py", line 366, in make_request
ErrorHandler.process(http_err)
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/libby_errors.py", line 86, in process
error = http_err.response.json()
^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/requests/models.py", line 975, in json
raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Traceback (most recent call last):
File "/opt/homebrew/lib/python3.11/site-packages/requests/models.py", line 971, in json
return complexjson.loads(self.text, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/homebrew/bin/odmpy", line 8, in <module>
sys.exit(main())
^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/__main__.py", line 27, in main
run()
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/odm.py", line 1175, in run
openbook, toc = libby_client.process_audiobook(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/libby.py", line 835, in process_audiobook
download_base, meta = self.prepare_loan(loan)
^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/libby.py", line 817, in prepare_loan
_ = self.make_request(
^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/libby.py", line 366, in make_request
ErrorHandler.process(http_err)
File "/opt/homebrew/lib/python3.11/site-packages/odmpy/libby_errors.py", line 86, in process
error = http_err.response.json()
^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/requests/models.py", line 975, in json
raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Version/Environment
odmpy-0.8.1
Describe the problem
When using the libby
commands, the token is written to the local folder. This is convenient if you only work in a single folder, but it would be nice if followed the (fairly standard) XDG Base Directory convention. So, the default settings config (if not specified; you could keep the flag) would be ~/.config/odmpy
.
You can put the settings there manually with the --settings
flag, but it's annoying to type that for every operation.
Version/Environment
odmpy 0.7.9 [Python 3.11.3-darwin]
Hi, I was wondering if odmpy is still being maintained? I am hoping so! Starting Friday, April 19. I have been unable to access my library books in Libby.
To Reproduce
I'm am on a Mac with OS Sonoma using odmpy Version 0.8.1. [Python 3.11.3-darwin]
In Terminal, if I enter odmpy libby, or my usual command line sequence to access and download my libarary books: "odmpy libby -m -c -d "audiobooks/" I get the following:
odmpy --version
here.An unexpected error has occurred
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/odmpy/libby.py", line 357, in make_request
res.raise_for_status()
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/requests/models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://sentry-read.svc.overdrive.com/chip/sync
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/odmpy/odm.py", line 846, in run
synced_state = libby_client.sync()
^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/odmpy/libby.py", line 457, in sync
res: Dict = self.make_request("chip/sync")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/odmpy/libby.py", line 366, in make_request
ErrorHandler.process(http_err)
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/odmpy/libby_errors.py", line 103, in process
raise ClientError(
odmpy.libby_errors.ClientError: <odmpy.libby_errors.ClientError; http_status=403, msg='403 Client Error: Forbidden for url: https://sentry-read.svc.overdrive.com/chip/sync', error_response='{"result":"missing_chip"}''>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/odmpy/libby.py", line 357, in make_request
res.raise_for_status()
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/requests/models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://sentry-read.svc.overdrive.com/chip/sync
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.11/bin/odmpy", line 8, in
sys.exit(main())
^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/odmpy/main.py", line 27, in main
run()
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/odmpy/odm.py", line 846, in run
synced_state = libby_client.sync()
^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/odmpy/libby.py", line 457, in sync
res: Dict = self.make_request("chip/sync")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/odmpy/libby.py", line 366, in make_request
ErrorHandler.process(http_err)
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/odmpy/libby_errors.py", line 103, in process
raise ClientError(
odmpy.libby_errors.ClientError: <odmpy.libby_errors.ClientError; http_status=403, msg='403 Client Error: Forbidden for url: https://sentry-read.svc.overdrive.com/chip/sync', error_response='{"result":"missing_chip"}''>
I love this app and am going to "send you a coffee" in hopes that this is still being maintained a fix or some help can be provided. Thanks you!
When we download and keep the ODM files using that --keepodm
flag, would it be possible to keep them in the folder with the MP3s, instead of in the current working directory? That would become especially handy when processing multiple books, so I don't lose track of which files go with which book. This wasn't a concern with your old mode of operation when the user provided the ODM file, but when operating in Libby mode things are different.
It is possible to download PDF documents attached to the ebook at the same time as downloading the MP3 files, or as a separate followup? I know some are available only as ADE documents, which raises more problems, but I don't even know if it's possible to automatically download any attached documents.
I tried the latest commit that removes the dependency for eyeD3 and it breaks the chapters function for this particular book: Ball Lightning by Cixin Liu
I think it might have something to do with the special characters in the names of some chapters (@, / ).
I tried other three books with regular characters (a-z, :, -) in the names and it worked fine.
**Chapters generated with 0.3.0**
00:00:00.000 Ball Lightning
00:00:37.988 Prelude
00:13:57.988 Part 1 - College
00:20:10.988 Part 1 - Strange Phenomena 1
00:30:12.988 Part 1 - Ball Lightning
00:58:15.981 Part 1 - Lin Yun 1
01:19:37.981 Part 1 - Zhang Bin
01:44:09.981 Part 1 - Strange Phenomena 2
01:50:22.342 Part 1 - A Bolt from the Blue
02:44:42.342 Part 1 - Seti@home
03:05:49.101 Part 1 - Siberia / Part 2 - Lighthouse Inspiration
04:16:13.545 Part 2 - General Lin Feng
04:34:22.545 Part 2 - Attack Bees
04:41:06.545 Part 2 - Skynet
05:13:31.545 Part 2 - Ball Lightning
05:20:51.545 Part 2 - Thunderballs
05:29:19.870 Part 2 - Ding Yi
05:43:27.870 Part 2 - Empty Bubbles
06:21:54.870 Part 2 - Macro-Electrons
06:34:23.766 Part 2 - Weapons
07:02:16.766 Part 2 - Observers
07:16:22.766 Part 2 - Burnt Chips
07:28:07.766 Part 2 - Strange Phenomena 3
07:33:24.403 Part 2 - The Nuclear Power Plant
08:07:15.403 Part 2 - Strange Phenomena 4
08:23:02.403 Part 3 - Tornadoes
08:37:37.020 Part 3 - Zhufeng
08:51:34.020 Part 3 - Chip Destruction
09:03:39.020 Part 3 - Ambush at Sea
09:52:43.639 Part 3 - Strings
10:19:18.639 Part 3 - The Special Leading Group
10:41:36.639 Part 3 - Macro-Fusion
10:59:45.033 Part 3 - Lin Yun 2
11:40:36.033 Part 3 - Victory
11:48:19.033 Part 3 - The Quantum Rose
12:04:18.033 Afterword
12:11:27.033 Closing
**Chapters generated with 0.4.0**
00:00:00.000 Prelude
12:11:27.033 Closing
12:11:27.034 Afterword
12:11:27.035 Ball Lightning
12:11:27.036 Part 2 - Skynet
12:11:27.037 Part 1 - College
12:11:27.038 Part 2 - Ding Yi
12:11:27.039 Part 2 - Weapons
12:11:27.040 Part 3 - Zhufeng
12:11:27.041 Part 3 - Strings
12:11:27.042 Part 3 - Victory
12:11:27.043 Part 1 - Lin Yun 1
12:11:27.044 Part 1 - Zhang Bin
12:11:27.045 Part 1 - Seti@home
12:11:27.046 Part 2 - Observers
12:11:27.047 Part 3 - Tornadoes
12:11:27.048 Part 3 - Lin Yun 2
12:11:27.049 Part 2 - Attack Bees
12:11:27.050 Part 2 - Burnt Chips
12:11:27.051 Part 2 - Thunderballs
12:11:27.052 Part 3 - Macro-Fusion
12:11:27.053 Part 2 - Empty Bubbles
12:11:27.054 Part 3 - Ambush at Sea
12:11:27.055 Part 1 - Ball Lightning
12:11:27.056 Part 2 - Ball Lightning
12:11:27.057 Part 2 - Macro-Electrons
12:11:27.058 Part 2 - General Lin Feng
12:11:27.059 Part 3 - Chip Destruction
12:11:27.060 Part 3 - The Quantum Rose
12:11:27.061 Part 1 - Strange Phenomena 1
12:11:27.062 Part 1 - Strange Phenomena 2
12:11:27.063 Part 2 - Strange Phenomena 3
12:11:27.064 Part 2 - Strange Phenomena 4
12:11:27.065 Part 1 - A Bolt from the Blue
12:11:27.066 Part 2 - The Nuclear Power Plant
12:11:27.067 Part 3 - The Special Leading Group
12:11:27.068 Part 1 - Siberia / Part 2 - Lighthouse Inspiration
The debug information list the chapters in the correct order in both cases.
debug v030.txt
debug v040.txt
Describe the problem
A clear and concise description of what the bug/error is. If there is an error traceback dump, paste the text here (please avoid screenshots).
To Reproduce
Please include the full command used, for example odmpy libby --direct
Version/Environment
Please paste the contents of odmpy --version
here.
Under windows...
$ ./run_tests.sh
./run_tests.sh: line 3: coverage: command not found
apparently coverage is not in the path when installed normally.
When I run a single coverage command with python -m: TEST_ODM environment var not defined
Apparently this is expected after reading the run_tests.sh, but it would be nice to be able to run these separately.
$ python -m coverage run --append -m unittest -v tests.OdmpyTests.test_info
test_info (tests.odmpy_tests.OdmpyTests.test_info)
`odmpy info test.odm` ... ERROR
======================================================================
ERROR: test_info (tests.odmpy_tests.OdmpyTests.test_info)
`odmpy info test.odm`
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\nnn\Documents\dev\odmpy\tests\odmpy_tests.py", line 33, in setUp
self.test_file = os.environ["TEST_ODM"]
~~~~~~~~~~^^^^^^^^^^^^
File "<frozen os>", line 679, in __getitem__
KeyError: 'TEST_ODM'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\nnn\Documents\dev\odmpy\tests\odmpy_tests.py", line 35, in setUp
raise RuntimeError("TEST_ODM environment var not defined.")
RuntimeError: TEST_ODM environment var not defined.
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
$ TEST_ODM="test_ref24.odm" python -m coverage run --append -m unittest -v tests.OdmpyTests.test_cover_fail_ref24
does work
Version/Environment
current head: 0db8641
Describe the problem
When processing a loan export to get the books I hadn't previously downloaded and moved to their final resting place, I find that the --selectid
option only downloads one book, the last ID on the list.
To Reproduce
Download your loan file odmpy libby --loans
, grab a few IDs from it. Run 'em using the batch mode:
odmpy libby --bookfolderformat './tmp/%(ID)s' --hideprogress --direct --selectid 4790886 4565785
Result:
odmpy Interactive Client for Libby ----------------------------------------------------------------------
Non-interactive mode. Downloading loans with IDs 4790886, 4565785...
Opening audiobook "The Lives of Bees"...
Downloading "The Lives of Bees" by "Thomas D. Seeley" in 12 parts...
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-01.mp3"
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-02.mp3"
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-03.mp3"
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-04.mp3"
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-05.mp3"
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-06.mp3"
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-07.mp3"
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-08.mp3"
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-09.mp3"
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-10.mp3"
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-11.mp3"
Error saving ID3: Invalid date string: 2019-05-28T04:00:00+00:00
Saved "tmp/4565785/the-lives-of-bees-part-12.mp3"
Downloaded acsm to "tmp/4790886/The Lives of Bees - Thomas D. Seeley.acsm"
No error printed, but it only got the one book. I've tried this with multiple IDs, no success.
Version/Environment
odmpy 0.8.1 [Python 3.10.12-linux]
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.