Giter Club home page Giter Club logo

overdrive's People

Contributors

amjith avatar chbrown avatar harman28 avatar hyshai avatar mmckinst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

overdrive's Issues

No such file or directory

Hello!

Really looking forward to being able to use this tool, but when I enter the commands, I receive the following:

sudo chmod +x /usr/local/bin/overdrive
chmod: /usr/local/bin/overdrive: No such file or directory

I've tried separating out the commands (as you mentioned in another issue), as far as I can tell, but I always get stopped with the "No such file..." error.

Any thoughts on why this would be the case? Thanks so much for making this tool for those of us that updated to Catalina!

Exit with descriptive message on missing executable

Some of the overdrive commands call executables that are not standard on all systems.

When one of these is needed, but not found on the calling machine, the script should exit with a descriptive error message, indicating precisely what executable was missing (perhaps even describing how to install it).

python script to extract chapters

Do with it as you wish. I still haven't updated this for python3, but it's really handy combined with https://github.com/ex-nerd/audiotools (wow, I feel old looking at the last-updated dates on those) to merge files into m4b files that can load into a dedicated audiobook app on a phone.

#!/usr/bin/env python2
#
# Use with build_m4b from https://github.com/ex-nerd/audiotools
# Due to overdrive low quality, there is no point in encoding aac files
# with better than: 64kbps stereo, HE, optimize for voice
#

import os, sys, re
import mutagen.id3 as id3
from mutagen.mp3 import MP3
from mutagen import File

from collections import OrderedDict

def timestr(secs):
    (secs, ms) = str(secs).split('.')
    ms    =  float(ms[0:3] + '.' + ms[3:])
    secs  = int(secs)
    hours = int(secs // 3600)
    secs  = secs % 3600
    mins  = int(secs // 60)
    secs  = secs % 60
    return '{0:02}:{1:02}:{2:02}.{3:03.0f}'.format(hours, mins, secs, ms)

def load_mp3(total, dir, file):
    path = os.path.join(dir, file)
    #mfile = File(path)
    #file = File('some.mp3') # mutagen can automatically detect format and type of tags
    #artwork = file.tags['APIC:'].data # access APIC frame and grab the image
    #with open('image.jpg', 'wb') as img:
    #    img.write(artwork) # write artwork to new image
    #artwork = mfile.tags['APIC:'].data # access APIC frame and grab the image
    #with open('{0}.jpg'.format(path), 'wb') as img:
    #    img.write(artwork) # write artwork to new image
    audio = MP3(path)
    print(audio.info.length) #, audio.info.bitrate
    m = id3.ID3(path)

    data = m.get('TXXX:OverDrive MediaMarkers')
    if not data:
        print("Can't find TXXX data point for {0}".format(file))
        print(m.keys())
        return
    info = data.text[0].encode("ascii", "ignore")
    #print info
    file_chapters = re.findall(r"<Name>\s*([^>]+?)\s*</Name><Time>\s*([\d:.]+)\s*</Time>", info, re.MULTILINE)
    chapters = []
    for chapter in file_chapters:
        (name, length) = chapter
        name = re.sub(r'^"(.+)"$', r'\1', name)
        name = re.sub(r'^\*(.+)\*$', r'\1', name)
        name = re.sub(r'\s*\([^)]*\)$', '', name) # ignore any sub-chapter markers from Overdrive
        name = re.sub(r'\s+\(?continued\)?$', '', name) # ignore any sub-chapter markers from Overdrive
        name = re.sub(r'\s+-\s*$', '', name)      # ignore any sub-chapter markers from Overdrive
        name = re.sub(r'^Dis[kc]\s+\d+\W*$', '', name)  # ignore any disk markers from Overdrive
        name = name.strip()
        t_parts = list(length.split(':'))
        t_parts.reverse()
        seconds = total + float(t_parts[0])
        if len(t_parts) > 1:
            seconds += (int(t_parts[1]) * 60)
        if len(t_parts) > 2:
            seconds += (int(t_parts[2]) * 60 * 60)
        chapters.append([name, seconds])
        print(name, seconds)
        #chapters = re.search(r'(\w+)', info)
    #print(repr(chapters))
    return (total + audio.info.length, chapters)
    return


    # try:
    #     if file.decode("utf-8") == new.decode("utf-8"):
    #         new = None
    # except:
    #     print "  FILE:  "+os.path.join(dirname, file)
    #     raise
    # # Return
    # return (m, new, changed)

def visit(arg, dirname, names):
    print(dirname)
    os.chdir(dirname)
    #parent = os.path.dirname(dirname)
    #thisdir = os.path.basename(dirname)
    #print thisdir
    # Parse the files
    total = 0;
    all_chapters = OrderedDict()
    for file in sorted(names):
        if file.endswith('.mp3'):
            (total, chapters) = load_mp3(total, dirname, file)
            for chapter in chapters:
                if chapter[0] in all_chapters.keys():
                    continue
                all_chapters[chapter[0]] = chapter[1]
    if len(all_chapters) > 0:
        with open('overdrive_chapters.txt', 'w') as file:
            for name, length in all_chapters.items():
                chapstr = u'{0} {1}'.format(timestr(length), name)
                print(chapstr)
                file.write(chapstr + '\n')
    #print(repr(all_chapters))



if len(sys.argv) > 1:
    path = os.path.abspath(sys.argv[1])
else:
    path = os.path.abspath('.')
print(path)

os.path.walk(path, visit, None)

License Error

Hello,

I recently started getting a License Error when trying to convert the odm files. This wasn't happening before.

userName-MBP Downloads % ~/.local/bin/overdrive download Red.odm
Generating random ClientID=C04D296C-73E8-4AD8-AE6D-912C6DEBF056
Using AcquisitionUrl=https://ofs.contentreserve.com/MP3LicenseAcquisitionService.svc/5aed893d-f197-4689-953a-af4100b28671
Using MediaID=416729fe-7fe4-43a5-84ec-10896faa9fc4-425
Using RawHash=C04D296C-73E8-4AD8-AE6D-912C6DEBF056|1.2.0|10.11.6|ELOSNOCAIDEMEVIRDREVO
Using Hash=3+10LjLJzc+88b6YMmgcdqWcHA0=
1003The requested license is either invalid or already acquired%
userName-MBP Downloads %

your assistance would be greatly appreciated.

Error: "Output already exists" during download, plus spurious chars in author and title

Greetings,

Environment: Ubuntu 20.04
Script version: Dated 4/29/2020 (tried downloading latest copy, same problem exists)

(Edited issue to resolve formatting problem with metadata excerpt)

I don't know if this is a problem with Overdrive itself, or if something changed in one of the prerequisite tools, but I am having the following problem when downloading items from Overdrive (note that this occurs with multiple different items, I am using this one merely as an example - also note that client and license information has been removed, as there doesn't appear to be a problem with acquiring and using the license):

tracy@tracy-HP:/media/tracy/Refurb/LibAB$ overdrive download 'Buying Time.odm'
License already acquired: Buying Time.odm.license
Using License=<license info removed></License>
Using ClientID=<removed> from License
Using Author=Joe Haldeman, 
Using Title=Buying Time-
Creating directory Joe Haldeman,  - Buying Time-
Downloading Joe Haldeman,  - Buying Time-/Buying Time--Part01.mp3
Downloaded Joe Haldeman,  - Buying Time-/Buying Time--Part01.mp3 successfully
Downloading Joe Haldeman,  - Buying Time-/Buying Time--
Downloaded Joe Haldeman,  - Buying Time-/Buying Time-- successfully
Downloading Joe Haldeman,  - Buying Time-/Buying Time--Part02.mp3
Downloaded Joe Haldeman,  - Buying Time-/Buying Time--Part02.mp3 successfully
Output already exists: Joe Haldeman,  - Buying Time-/Buying Time--
Downloading Joe Haldeman,  - Buying Time-/Buying Time--Part03.mp3
Downloaded Joe Haldeman,  - Buying Time-/Buying Time--Part03.mp3 successfully
Output already exists: Joe Haldeman,  - Buying Time-/Buying Time--
Downloading Joe Haldeman,  - Buying Time-/Buying Time--Part04.mp3
Downloaded Joe Haldeman,  - Buying Time-/Buying Time--Part04.mp3 successfully
Output already exists: Joe Haldeman,  - Buying Time-/Buying Time--
Downloading Joe Haldeman,  - Buying Time-/Buying Time--Part05.mp3
Downloaded Joe Haldeman,  - Buying Time-/Buying Time--Part05.mp3 successfully
Output already exists: Joe Haldeman,  - Buying Time-/Buying Time--
Downloading Joe Haldeman,  - Buying Time-/Buying Time--Part06.mp3
Downloaded Joe Haldeman,  - Buying Time-/Buying Time--Part06.mp3 successfully
Output already exists: Joe Haldeman,  - Buying Time-/Buying Time--
Downloading Joe Haldeman,  - Buying Time-/Buying Time--Part07.mp3
Downloaded Joe Haldeman,  - Buying Time-/Buying Time--Part07.mp3 successfully
Output already exists: Joe Haldeman,  - Buying Time-/Buying Time--
Downloading Joe Haldeman,  - Buying Time-/Buying Time--Part08.mp3
Downloaded Joe Haldeman,  - Buying Time-/Buying Time--Part08.mp3 successfully
Output already exists: Joe Haldeman,  - Buying Time-/Buying Time--
Downloading Joe Haldeman,  - Buying Time-/Buying Time--Part09.mp3
Downloaded Joe Haldeman,  - Buying Time-/Buying Time--Part09.mp3 successfully
Output already exists: Joe Haldeman,  - Buying Time-/Buying Time--
Using CoverUrl=https://images.contentreserve.com/ImageType-100/6578-1/%7BCD9D8596-387E-4F84-A4A3-8734E1F6D941%7DImg100.jpg
Downloading Joe Haldeman,  - Buying Time-/folder.jpg
Downloaded cover image successfully
tracy@tracy-HP:/media/tracy/Refurb/LibAB$ 

Note on the Title and Author lines the spurious characters after the names (the comma after the author, and the dash after the title). Also note the repeated "Output already exists" lines (after each download except the first).

I have successfully used the script in the past (back in early May), but at that time I was running Ubuntu 19.10 (I did a clean install when I moved to 20.04, so it is possible that some underlying dependency changed, or even is missing).

Here are what I think are the relevant lines from the odm files (I can provide the entire odm file, if that will be helpful):

	<![CDATA[<Metadata>
	<ContentType>MP3 Audio Book</ContentType>
	<Title>Buying Time</Title>
	<SortTitle>Buying Time</SortTitle>
	<Publisher>Novel Audio</Publisher>
	<ThumbnailUrl>https://images.contentreserve.com/ImageType-200/6578-1/{CD9D8596-387E-4F84-A4A3-8734E1F6D941}Img200.jpg</ThumbnailUrl>
	<CoverUrl>https://images.contentreserve.com/ImageType-100/6578-1/{CD9D8596-387E-4F84-A4A3-8734E1F6D941}Img100.jpg</CoverUrl>
	<Creators>
		<Creator role="Author" file-as="Haldeman, Joe">Joe Haldeman</Creator>
		<Creator role="Narrator" file-as="Vale, Eric">Eric Vale</Creator>
	</Creators>

And here is how the same data appears in the metadata file:

<Metadata>
<ContentType>MP3 Audio Book</ContentType>
<Title>Buying Time</Title>
<SortTitle>Buying Time</SortTitle>
<Publisher>Novel Audio</Publisher>
<ThumbnailUrl>https://images.contentreserve.com/ImageType-200/6578-1/{CD9D8596-387E-4F84-A4A3-8734E1F6D941}Img200.jpg</ThumbnailUrl>
<CoverUrl>https://images.contentreserve.com/ImageType-100/6578-1/{CD9D8596-387E-4F84-A4A3-8734E1F6D941}Img100.jpg</CoverUrl>
<Creators>
<Creator role="Author" file-as="Haldeman, Joe">Joe Haldeman</Creator>
<Creator role="Narrator" file-as="Vale, Eric">Eric Vale</Creator>
</Creators>

Any ideas what might be going wrong?

Ubuntu bash on WSL hates returns

Kudos! I got this working on Ubuntu on WSL with Win10. Only notable issue I had was the overdrive.sh script has carriage returns as well as newlines. I ran it through sed to delete the returns (s/\r//) and now it seems to be working.

Check that files in MEDIA array exist

Current behavior is just to assume all supplied paths are good; if a path is missing, xmllint will fail with a cryptic error message:

$ overdrive download DoesNotExist.odm
Generating random ClientID=B49967C8-61F8-4365-88E0-F5C822B13235
warning: failed to load external entity "DoesNotExist.odm"

This is an unusual error case, but when it does arise, the fatal "warning" can be confusing / misleading, and the proper solution of explicitly checking for existence as a preliminary step is trivial.

See, e.g., #40, comments 3–4.

HTTP errors swallow potentially useful response content

The --fail flag in curl -o my.out --fail ... handily avoids writing invalid responses to my.out when the HTTP status code is an error, but unfortunately also causes the response body to be completely omitted, making it difficult to determine what the problem was.

AFAIK, there is no combination of curl flags to treat response content distinctly differently based on the returned HTTP status being an error or not. Ideally, I'd like to:

  1. On HTTP 200 OK (or any 2** code, ideally), write response body to given output file and return exit code 0 so that the script (running with set -e) continues apace
  2. On any error, print response body to stdout (or stderr, whichever), do not write to the given file, and return a non-zero exit code so that the script exits

That's pretty much what currently happens with -o ... --fail, except for the bold bit.

Verify license acquisition succeeded

Either by checking the file contents or the result of the curl call in acquire_license.

(Debugging upstream errors requires a tedious extra step if the license fails; see #3)

uuid replaced by uuidgen in mac OS 10.14

The script returns a License error since the command uuid is not available in mac OS Mojave (10.14) and can't be easily installed via brew.
There is a similar command available uuidgen that provides the same functionality (generating a random UUID).
A simple solution is to create an alias in bash uudi -> uuidgen or replace the single use of uuid in the script by uuidgen

Does this work in Windows?

I used this in Linux, but does this work in Windows too?
If it doesn't, can anyone recommend a Windows program that works.

Python CLI for Libby - link to repo

Hi, great project you have here.
I noticed that you updated the readme on the topic of Libby the other day. I'm not trying to steal attention away from this project, I just wanted to show you what I've been working on lately now that it's clear that the legacy OverDrive app is being discontinued in early 2023 and odm's might go away.

PyLibby

It's a CLI for Libby written in python. It can download audiobooks from Libby without the odm the same way as their online app does.

I mainly enjoy the part of programming that involves figuring out how stuff works, not so much the maintenance part, so please feel free to fork.

Add Dependency Package Names / Commands To Docs/Readme

First of all, thank you for this awesome program. It works so much better than WINE's overdrive app on linux.

Just one small suggestion (you don't need to do it but it might help some people). For the 'Prerequisites' section, add this to make it easier for people to figure out the actual package names to install. Another idea is to list one liner commands for each major OS (mac, windows, debian, red hat, arch, etc)

  • curl
  • uuidgen (uuid-runtime)
  • xmllint (libxml2-utils)
  • iconv (libc6-dev)
  • openssl
  • base64 (cl-base64)
  • tidy

parser error : Document is empty

overdrive.sh successfully downloads 6 out of 10 parts but then tells me "...metadata:1: parser error : Document is empty". I realized from the first error output that the command "tidy" was not installed, so I installed it and tried overdrive.sh again, no dice. Here is the output:

ryan@pocketwee:~/Books$ overdrive download DontBurnThisBookThinkingforYourselfinAnAgeofUn-683.odm 
License already acquired: DontBurnThisBookThinkingforYourselfinAnAgeofUn-683.odm.license
Using License=<License xmlns="http://license.overdrive.com/2008/03/License.xsd" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><SignedInfo><Version>1.0</Version><ContentID>d1ef3dc1-c3b0-4a09-a89d-fbb31252a84a-425</ContentID><ClientID>E54A3A57-40E2-4F2F-928D-EA665B9B5872</ClientID></SignedInfo><Signature>MmaVqIzcTm5sA8pbZoGYbt4DonXUiG+fm+Cwp9lGS7c3CnxM/OYArYqi5lH40mfXdTcT0hQPYF5F2avDdHE/EAqczJus9fssGMBgy946DtTH8ca+pCuX1tZExctFOmIrQPxnhIdMkB4IJMd4MZVYhSZyKmm/8PDhq2HzAcRnn6o=</Signature></License>
Using ClientID=E54A3A57-40E2-4F2F-928D-EA665B9B5872 from License
DontBurnThisBookThinkingforYourselfinAnAgeofUn-683.odm.metadata:1: parser error : Document is empty

^
seq: invalid floating point argument: ‘’
Try 'seq --help' for more information.
Using Author=
DontBurnThisBookThinkingforYourselfinAnAgeofUn-683.odm.metadata:1: parser error : Document is empty

^
Using Title=
Creating directory  - 
Output already exists:  - /Part01.mp3
Output already exists:  - /Part02.mp3
Output already exists:  - /Part03.mp3
Output already exists:  - /Part04.mp3
Output already exists:  - /Part05.mp3
Output already exists:  - /Part06.mp3
DontBurnThisBookThinkingforYourselfinAnAgeofUn-683.odm.metadata:1: parser error : Document is empty

^
Using CoverUrl=
Cover image not available
ryan@pocketwee:~/Books$ 

Libby

Hi. I've really enjoyed using your script over the last couple of years.
Have you, by chance, looked at the new Libby app? It looks like Overdrive is going away in January 2023 and Libby doesn't allow direct downloading of any files.

Just wondered if you've given it any thought?

Thanks

Is there a way to pull chapter timestamps out as we're doing this?

I don't know much about the back end of how this works, I'm admittedly very new to this world but this whole project has encouraged me to learn how to use bash scripts and python so I'm slowly getting a feel for it.

I've written a script that allows me to decipher the table of contents from the overdrive "listen in browser" feature and extract the time stamps to use as label markers to edit chapters, but that process still forces me to manually enter into the inspect element for each book. Curious if there's any way to pull that information out at the same time we're pulling the downloads.

Or if that just doesn't make sense for this specific project I'll find another solution. Thanks for all you do!

Document is empty error

Thanks for putting together this script....
I have a couple of audio books checked out with .odm files on my computer. Every time I run overdrive download command I get this:

Generating random ClientID=AD447C67-5C73-4916-9F5E-92B680865419
Using AcquisitionUrl=https://ofs.contentreserve.com/MP3LicenseAcquisitionService.svc/158190f9-969d-4f8d-b8e3-ad8700b591a5
Using MediaID=e3cb0c48-c689-4515-9aeb-a6f0cf4bf425-425
Using RawHash=AD447C67-5C73-4916-9F5E-92B680865419|1.2.0|10.11.6|ELOSNOCAIDEMEVIRDREVO
Using Hash=1mwwKSyHYpTMxkPIccML3GJLIY0=
Using License=1.0e3cb0c48-c689-4515-9aeb-a6f0cf4bf425-425AD447C67-5C73-4916-9F5E-92B680865419UaD0d2lqOJos6mQiYUkn4LRSr+ilWRsnWoAN/NB98PTGDmcZbf2fEYZj9lO4s5dYkYzzH+h6HOXzBaaen9JNSwcl1fp4qwpnl3EPBaZ1GvSaOEPafpJnTO9Kd74P/lx92vNGzLvpn+ivS8j01kkcLRAFjuFhaSyaG73pcr1FLlM=
Using ClientID=AD447C67-5C73-4916-9F5E-92B680865419 from License
/home/user/.local/bin/overdrive: line 127: tidy: command not found
audiobookfilename.odm.metadata:1: parser error : Document is empty

(my user directory and odm file name changed for privacy but they are correct in the original output.

I have no idea how to interpret that... Any ideas?

any idea how we can use libby?

Screenshot 2022-09-22 at 10-59-01 Libby - Rather Be the Devil

as many people already know, overdrive is being phased out after years of being assured that both overdrive and libby will continue side by side. anyways, this is the screen on libby via their website.
This means when overdrive will sunset, we will be left with no way to download mp3s. Has anyone found a way to de-drm libby files?

Integrate with LazyLibrarian

I'm using LazyLibrarian to replenish my audiobook library which I lost a little while ago, and while it's pretty good at giving a graphical display of a lot of the content, it's woeful at organising the metadata (using GoodReads as its primary source of truth, which helps for book details, but is rubbish for things like chapters etc).

Using OverDrive appears to be a natural means to resolve that, both in terms of grabbing great quality files, as well as well managed files in terms of chapters etc.

LazyLibrarian has the options to blend files together, and uses a range of options (including FFMPEG) to do so, but still relies on the file data from somewhere.

So I think it would be great to get these two working in harmony together.

Missing LICENSE

I see you have no LICENSE file for this project. The default is copyright.

I would suggest releasing the code under the GPL-3.0-or-later or AGPL-3.0-or-later license so that others are encouraged to contribute changes back to your project.

overdrive command not found

After installing and then trying to download the book, it tells me "zsh: command not found: overdrive". I'm closed Terminal and reinstalled the first command with the same result. Help please.

Not working for MacOS Catalina Version 10.15.3

Hi @chbrown, first of all, thank you for doing this. I'm sure once I get it going correctly, this will be such an amazing tool to have.

I don't have any experience coding or using Terminal, so it's more than likely I'm not doing something right, but when I copy/paste the code listed on your GitHub, I get the following:

% mkdir -p ~/.local/bin
curl https://chbrown.github.io/overdrive/overdrive.sh -o ~/.local/bin/overdrive
chmod +x ~/.local/bin/overdrive
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8911  100  8911    0     0  27760      0 --:--:-- --:--:-- --:--:-- 27760

Then I move on to step 2 and type overdrive and get the following:

Usage: overdrive [-h|--help]
       overdrive --version
       overdrive command [command2 ...] book.odm [book2.odm ...] [-v|--verbose]

Commands:
  download   Download the mp3s for an OverDrive book loan.
  return     Process an early return for an OverDrive book loan.
  info       Print the author, title, and total duration (in seconds) for each OverDrive loan file.
  metadata   Print all metadata from each OverDrive loan file.

You must supply at least one command.
You must supply at least one media file (the .odm extension is required).

So all seems to be working well. But then I input the download code and get the following:

% cd ~/Downloads
overdrive download LilyandtheOctopus-9077.odm
License already acquired: LilyandtheOctopus-9077.odm.license
Using License=
LilyandtheOctopus-9077.odm.license:1: parser error : Document is empty

^

I have the .license file that goes along with the .odm file, but nothing happens at this point and I can't seem to figure out a way to fix anything.

Any help would be greatly appreciated!

Downloaded MP3 files have very low volume

I've noticed that all the audio MP3 files downloaded via this script are very low volume. What's odd is that when I listen to the book in Libby or Overdrive's other apps, the volume is perfectly fine. (Libby at 60% volume on my iPhone requires 95% or 100% volume) Is there a way to adjust this in the script? (E.g. changing the encoding options?)

I have no idea what I'm doing :)

I try to download the .odm file, and I am getting this error message:

-bash: cd: /Users/BethAnne1/Downloads/Users/BethAnne1/Downloads/UnbrokenTheYoungAdultAdaptationAnOlympiansJour-584.odm: No such file or directory

Partial downloads aren't finished when rerunning

Program was interrupted during a download and upon rerunning, the last partially downloaded file was skipped because it already existed, even though it was not completely downloaded. Instead of just checking if the file exists, you need to also check the byte count. Probably could just let curl handle that by passing it --continue-at -.

overdrive: xmlstarlet: command not found

Hey chbrown! I was an avid Overdrive user and I'm using your overdrive thingie to brace myself for the upgrade to Catalina which breaks Overdrive. I'm a noob to GitHub and pretty much even Terminal, but I'm fearless. I followed the instructions to install it, borrowed a book an downloaded the .odm. Issued the command and got the xmlstarlet command not found. Maybe there's some kind of developer commands I don't have installed. Can you help?

I created a gist but I'm not sure of the proper protocol for giving it to you so I'll include the embed link and the verbose text itself.

<script src="https://gist.github.com/AlpacaLips99/212e18504eec99f1bdbb2b9f4269d82f.js"></script>

Corys-MacBook-Pro:Downloads coryengel$ overdrive download WakingGodsThemisFilesSeriesBook02-63028.odm --verbose

  • printf 'Entering debug (verbose) mode\n'
    Entering debug (verbose) mode
  • shift
  • [[ 0 -gt 0 ]]
  • [[ 1 -eq 0 ]]
  • [[ 1 -eq 0 ]]
  • HEADER_PRINTED=
  • for ODM in '"${MEDIA[@]}"'
  • for COMMAND in '"${COMMANDS[@]}"'
  • case $COMMAND in
  • download WakingGodsThemisFilesSeriesBook02-63028.odm
  • license_path=WakingGodsThemisFilesSeriesBook02-63028.odm.license
  • acquire_license WakingGodsThemisFilesSeriesBook02-63028.odm WakingGodsThemisFilesSeriesBook02-63028.odm.license
  • [[ -e WakingGodsThemisFilesSeriesBook02-63028.odm.license ]]
    ++ uuidgen
    ++ tr '[:lower:]' '[:upper:]'
  • ClientID=FB5EB1EB-7305-4845-A4B8-EA005CC5D5DE
  • printf 'Generating random ClientID=%s\n' FB5EB1EB-7305-4845-A4B8-EA005CC5D5DE
    Generating random ClientID=FB5EB1EB-7305-4845-A4B8-EA005CC5D5DE
    ++ xmlstarlet sel -t -v /OverDriveMedia/License/AcquisitionUrl WakingGodsThemisFilesSeriesBook02-63028.odm
    /usr/local/bin/overdrive: line 70: xmlstarlet: command not found
  • AcquisitionUrl=

delete me

I got the ODM from my library's overdrive website, but the overdrive script no longer works. Is this overdrive script dead, now that the Overdrive app no longer works?

Yes, I did read the section on "Libby" in the readme (https://github.com/chbrown/overdrive#libby), but just wanted to confrim.

Missing last chapter

I borrowed The Hitchhiker's Guide to the Galaxy and downloaded the mp3 files. There are 5 chapters in the odm file (copied below) but the script only downloaded 4 files. I suspect it is due to the missing newline at the end of the output from the extract_filenames function.

Here's is the odm file:

<?xml version="1.0"?>
<OverDriveMedia id="1c96507d-f48d-4fef-b190-130ce15c8fa8-425" ODMVersion="3.0.0.0" OMCVersion="3.0.0.0">
	<License>
		<AcquisitionUrl>https://ofs.contentreserve.com/MP3LicenseAcquisitionService.svc/a9368c50-6b29-44d3-bed2-ab8900003648</AcquisitionUrl>
	</License><![CDATA[<Metadata>
	<ContentType>MP3 Audio Book</ContentType>
	<Title>The Hitchhiker's Guide to the Galaxy</Title>
	<SubTitle>The Hitchhiker's Guide to the Galaxy Series, Book 1</SubTitle>
	<SortTitle>Hitchhikers Guide to the Galaxy The Hitchhikers Guide to the Galaxy Series Book 01</SortTitle>
	<Publisher>Penguin Random House Audio Publishing Group</Publisher>
	<Series>The Hitchhiker's Guide to the Galaxy</Series>
	<ThumbnailUrl>https://images.contentreserve.com/ImageType-200/1191-1/{1C96507D-F48D-4FEF-B190-130CE15C8FA8}Img200.jpg</ThumbnailUrl>
	<CoverUrl>https://images.contentreserve.com/ImageType-100/1191-1/{1C96507D-F48D-4FEF-B190-130CE15C8FA8}Img100.jpg</CoverUrl>
	<Creators>
		<Creator role="Author" file-as="Adams, Douglas">Douglas Adams</Creator>
		<Creator role="Narrator" file-as="Fry, Stephen">Stephen Fry</Creator>
	</Creators>
	<Subjects>
		<Subject id="26">Fiction</Subject>
		<Subject id="80">Science Fiction</Subject>
		<Subject id="98">Science Fiction &amp; Fantasy</Subject>
	</Subjects>
	<Languages>
		<Language code="en">English</Language>
	</Languages>
<Description>&lt;b&gt;&lt;i&gt;NEW YORK TIMES &lt;/i&gt;BESTSELLER &#8226; "Extremely funny . . . inspired lunacy . . . [and] over much too soon."&#8212;&lt;i&gt;The Washington Post Book World&lt;/i&gt;&lt;/b&gt;&lt;br&gt;&lt;b&gt;Nominated as one of America's best-loved novels by PBS's &lt;i&gt;The Great American Read&lt;/i&gt;&lt;/b&gt;&lt;br&gt;Seconds before Earth is demolished to make way for a galactic freeway, Arthur Dent is plucked off the planet by his friend Ford Prefect, a researcher for the revised edition of &lt;i&gt;The Hitchhiker's Guide to the Galaxy &lt;/i&gt;who, for the last fifteen years, has been posing as an out-of-work actor.&lt;br&gt;Together, this dynamic pair began a journey through space aided by a galaxyful of fellow travelers: Zaphod Beeblebrox&#8212;the two-headed, three-armed ex-hippie and totally out-to-lunch president of the galaxy; Trillian (formerly Tricia McMillan), Zaphod's girlfriend, whom Arthur tried to pick up at a cocktail party once upon a time zone; Marvin, a paranoid, brilliant, and chronically depressed robot; and Veet Voojagig, a former...</Description>
</Metadata>]]><DrmInfo>
	<PlayOnPC>1</PlayOnPC>
	<PlayOnPCCount>-1</PlayOnPCCount>
	<BurnToCD>1</BurnToCD>
	<BurnToCDCount>-1</BurnToCDCount> 
	<PlayOnPM>1</PlayOnPM>
	<TransferToSDMI>1</TransferToSDMI> 
	<TransferToNonSDMI>1</TransferToNonSDMI> 
	<TransferCount>-1</TransferCount>
	<CollaborativePlay>0</CollaborativePlay>
	<PublicPerformance>0</PublicPerformance>
	<TranscodeToAAC>1</TranscodeToAAC>
<ExpirationDate>2020-04-15T04:00:37Z</ExpirationDate><Hash>psH5vw10Ee2JHYeevPcyybsMdGk=</Hash><Hash2>7N3xlqEPZMb2WghFVIRuRBkn1Ak=</Hash2></DrmInfo><Formats><Format name="Medium Quality"><Quality level="Medium" /><Protocols><Protocol method="download" baseurl="https://mp3audio-gk.cdn.overdrive.com/MP3AudioStore1" /></Protocols><Parts count="5"><Part number="1" filesize="36500043" name="Part 1" filename="1191-1\1C9\650\7D\{1C96507D-F48D-4FEF-B190-130CE15C8FA8}Fmt425-Part01.mp3" duration="75:54" /><Part number="2" filesize="34837193" name="Part 2" filename="1191-1\1C9\650\7D\{1C96507D-F48D-4FEF-B190-130CE15C8FA8}Fmt425-Part02.mp3" duration="72:26" /><Part number="3" filesize="33988318" name="Part 3" filename="1191-1\1C9\650\7D\{1C96507D-F48D-4FEF-B190-130CE15C8FA8}Fmt425-Part03.mp3" duration="70:40" /><Part number="4" filesize="31996742" name="Part 4" filename="1191-1\1C9\650\7D\{1C96507D-F48D-4FEF-B190-130CE15C8FA8}Fmt425-Part04.mp3" duration="66:31" /><Part number="5" filesize="31771462" name="Part 5" filename="1191-1\1C9\650\7D\{1C96507D-F48D-4FEF-B190-130CE15C8FA8}Fmt425-Part05.mp3" duration="66:03" /></Parts></Format></Formats><Source id="SanJose"><Name>San José Digital Library</Name><WebsiteUrl>http://overdrive.sjlibrary.org</WebsiteUrl><BannerUrl>http://overdrive.sjlibrary.org/ODMBanner.gif</BannerUrl><AccentColor>#eeeeee</AccentColor></Source><TransactionID>022-1693196-00045</TransactionID><EarlyReturnURL>https://notifications-ofs.contentreserve.com/EarlyReturn/SanJose/022-1693196-00045/1c96507d-f48d-4fef-b190-130ce15c8fa8-425?h=3sMV0nvFR5zf%2fqEj9DvuFbXnRbf9Lbz2vdouyzTJ5t8%3d</EarlyReturnURL><DownloadSuccessURL>https://notifications-ofs.contentreserve.com/DownloadSuccess/SanJose/022-1693196-00045/1c96507d-f48d-4fef-b190-130ce15c8fa8-425?h=3sMV0nvFR5zf%2fqEj9DvuFbXnRbf9Lbz2vdouyzTJ5t8%3d</DownloadSuccessURL></OverDriveMedia>```

ln 66: uuid: command not found

getting an error when trying to use this

looks amazing! hope you can help. here's the debug log below:

do you know what this means?

~/D/b/odm ❯❯❯ overdrive download multipart.odm --verbose
+ printf 'Entering debug (verbose) mode\n'
Entering debug (verbose) mode
+ shift
+ [[ 0 -gt 0 ]]
+ [[ 1 -eq 0 ]]
+ [[ 1 -eq 0 ]]
+ HEADER_PRINTED=
+ for ODM in '"${MEDIA[@]}"'
+ for COMMAND in '"${COMMANDS[@]}"'
+ case $COMMAND in
+ download multipart.odm
+ license_path=multipart.odm.license
+ acquire_license multipart.odm multipart.odm.license
+ [[ -e multipart.odm.license ]]
++ uuid
++ tr /a-z/ /A-Z/
/usr/local/bin/overdrive: line 66: uuid: command not found
+ ClientID=
+ printf 'Generating random ClientID=%s\n' ''
Generating random ClientID=
++ xmlstarlet sel -t -v /OverDriveMedia/License/AcquisitionUrl multipart.odm
/usr/local/bin/overdrive: line 70: xmlstarlet: command not found
+ AcquisitionUrl=

License acquisition error "Missing Query Parameter" silently ignored

After running
overdrive download myBook.odm
The .license is created and I get this error:
Using License=<LicenseError xmlns="http://license.overdrive.com/2008/03/LicenseError.xsd" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ErrorCode>1001</ErrorCode><ErrorMessage>Missing Query Parameter</ErrorMessage><ErrorDetails i:nil="true"/></LicenseError>
Any ideas what's going on and how can I fix it?

syntax error near unexpected token `newline' when downloading an .odm file

Hi @chbrown,

Thank you for creating an amazing OverDrive script that is so helpful! I am getting the following error when I try and download an .odm file. I did not see others with a similar issue. I have tried a few .odm files from my local library. Here are the commands and responses. I also attached the .odm file (not I had to change the extension to .zip to upload, but you can just change it back to .odm).

MacBook-Air:Downloads kmesser$ ~/.local/bin/overdrive download Downloads/Sentence.odm 
/Users/kmesser/.local/bin/overdrive: line 1: syntax error near unexpected token `newline'
/Users/kmesser/.local/bin/overdrive: line 1: `<!DOCTYPE html>'

Thanks so much for the help!
Sentence.zip

Adam

License is invalid Error

On MacOS

user@MBP Audiobooks % overdrive download HackingGrowthHowTodaysFastestGrowingCompaniesD-630.odm --verbose
Entering debug (verbose) mode
+ CURLOPTS=("${CURLOPTS[@]:1}")
+ shift
+ [[ 0 -gt 0 ]]
+ [[ 1 -eq 0 ]]
+ [[ 1 -eq 0 ]]
+ HEADER_PRINTED=
+ for ODM in '"${MEDIA[@]}"'
+ for COMMAND in '"${COMMANDS[@]}"'
+ case $COMMAND in
+ download HackingGrowthHowTodaysFastestGrowingCompaniesD-630.odm
+ license_path=HackingGrowthHowTodaysFastestGrowingCompaniesD-630.odm.license
+ acquire_license HackingGrowthHowTodaysFastestGrowingCompaniesD-630.odm HackingGrowthHowTodaysFastestGrowingCompaniesD-630.odm.license
+ [[ -e HackingGrowthHowTodaysFastestGrowingCompaniesD-630.odm.license ]]
++ uuidgen
++ tr '[:lower:]' '[:upper:]'
+ ClientID=C426F217-3A9C-4C7A-9B1F-A490C0E7D77F
+ printf 'Generating random ClientID=%s\n' C426F217-3A9C-4C7A-9B1F-A490C0E7D77F
Generating random ClientID=C426F217-3A9C-4C7A-9B1F-A490C0E7D77F
++ xmllint --xpath '/OverDriveMedia/License/AcquisitionUrl/text()' HackingGrowthHowTodaysFastestGrowingCompaniesD-630.odm
+ AcquisitionUrl=https://ofs.contentreserve.com/MP3LicenseAcquisitionService.svc/e610fc69-54f9-4ce5-aa85-acad00e8cf8c
+ printf 'Using AcquisitionUrl=%s\n' https://ofs.contentreserve.com/MP3LicenseAcquisitionService.svc/e610fc69-54f9-4ce5-aa85-acad00e8cf8c
Using AcquisitionUrl=https://ofs.contentreserve.com/MP3LicenseAcquisitionService.svc/e610fc69-54f9-4ce5-aa85-acad00e8cf8c
++ xmllint --xpath 'string(/OverDriveMedia/@id)' HackingGrowthHowTodaysFastestGrowingCompaniesD-630.odm
+ MediaID=12be9ca6-db3c-4013-a000-fce166918282-425
+ printf 'Using MediaID=%s\n' 12be9ca6-db3c-4013-a000-fce166918282-425
Using MediaID=12be9ca6-db3c-4013-a000-fce166918282-425
+ RawHash='C426F217-3A9C-4C7A-9B1F-A490C0E7D77F|1.2.0|10.11.6|ELOSNOC*AIDEM*EVIRDREVO'
+ printf 'Using RawHash=%s\n' 'C426F217-3A9C-4C7A-9B1F-A490C0E7D77F|1.2.0|10.11.6|ELOSNOC*AIDEM*EVIRDREVO'
Using RawHash=C426F217-3A9C-4C7A-9B1F-A490C0E7D77F|1.2.0|10.11.6|ELOSNOC*AIDEM*EVIRDREVO
++ echo -n 'C426F217-3A9C-4C7A-9B1F-A490C0E7D77F|1.2.0|10.11.6|ELOSNOC*AIDEM*EVIRDREVO'
++ iconv -f ASCII -t UTF-16LE
++ openssl dgst -binary -sha1
++ base64
+ Hash=/tHikPT0xw1zmVW9B3KunnyXxEA=
+ printf 'Using Hash=%s\n' /tHikPT0xw1zmVW9B3KunnyXxEA=
Using Hash=/tHikPT0xw1zmVW9B3KunnyXxEA=
+ curl -L -A 'OverDrive Media Console' --compressed 'https://ofs.contentreserve.com/MP3LicenseAcquisitionService.svc/e610fc69-54f9-4ce5-aa85-acad00e8cf8c?MediaID=12be9ca6-db3c-4013-a000-fce166918282-425&ClientID=C426F217-3A9C-4C7A-9B1F-A490C0E7D77F&OMC=1.2.0&OS=10.11.6&Hash=/tHikPT0xw1zmVW9B3KunnyXxEA='
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   286    0   286    0     0    729      0 --:--:-- --:--:-- --:--:--   729
++ cat HackingGrowthHowTodaysFastestGrowingCompaniesD-630.odm.license
+ printf 'Using License=%s\n' '<LicenseError xmlns="http://license.overdrive.com/2008/03/LicenseError.xsd" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ErrorCode>1003</ErrorCode><ErrorMessage>The requested license is either invalid or already acquired</ErrorMessage><ErrorDetails i:nil="true"/></LicenseError>'
Using License=<LicenseError xmlns="http://license.overdrive.com/2008/03/LicenseError.xsd" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ErrorCode>1003</ErrorCode><ErrorMessage>The requested license is either invalid or already acquired</ErrorMessage><ErrorDetails i:nil="true"/></LicenseError>
++ xmllint --xpath '//*[local-name()="ClientID"]/text()' HackingGrowthHowTodaysFastestGrowingCompaniesD-630.odm.license
XPath set is empty
+ ClientID=
user@MBP Audiobooks % 
```

newb I/O error : Operation not permitted warning: failed to load external entit

Hi chbrown, I'm new to all this/terminal, just trying to get some audiobooks for commuting now that we are back to in-office work. I sure I'm screwing something up but when I run the command this is what is outputs in terminal. If you tell me how to send debug I can do that also:
"user"@"users"-MacBook-Air Downloads % cd ~/Downloads
~/.local/bin/overdrive download "name of book"_9781984891747_4348059-2.odm
Generating random ClientID=E16EACF5-156C-400A-8784-646E376A0B52
I/O error : Operation not permitted
I/O error : Operation not permitted
warning: failed to load external entity ""name of book"_9781984891747_4348059-2.odm"

I put " " around things I assume I don't want on here except the last line that does have ""

If I copy your command this is what it spits out, so I think??? I installed it correctly:
"user"@"users"-MacBook-Air Downloads % cd ~/Downloads
~/.local/bin/overdrive download Novel.odm
Specified media file does not exist: Novel.odm

again really sorry for what I assume is 100% user error because I'm old and this is new to me. thanks for any help.

linux support

i'm on linux and trying this out. i got some odm files from the library, and tried to download the mp3. it seems i'm getting an empty .metadata file. the error is:

.odm.metadata:1: parser error : Document is empty

i see a .metadata file, but it's indeed empty. any ideas or helps on what to try?

Process substitution not supported by Alpine Linux on iOS

I’ve successfully run this great script on macOS, and I’m attempting to run in an iOS environment via Alpine Linux.

I’ve been able to install all of the requisite packages via apk add, and while the script runs, I get the following error when trying to run the download command: “ line 264: /dev/fd/63: No such file or directory”

When running in verbose mode, the error seems to occur as each of the parts are being iterated for download; that is, the directory is successfully made, the part file names are identified, but the download process does not start, nor does it throw a download fail error. Any thoughts?

License Retrivial Fails

Hi there,

It appears that overdrive has changed the the license API. I'm getting this for the contents of my .odm.license.

<LicenseError xmlns="http://license.overdrive.com/2008/03/LicenseError.xsd" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ErrorCode>1001</ErrorCode><ErrorMessage>Missing Query Parameter</ErrorMessage><ErrorDetails i:nil="true"/></LicenseError>

Cheers, Jon

Make commands permanent

Hi,
I am not a programmer, so it could be that this is basic knowledge. Hope you can help me.
I love using your Overdrive script to get my books, so I can listen to them on other devices. I have it working with just one little issue. Every time I use it, I have to enter the commands you mention in the text below before I can do cd Downloads ---> Overdrive Download MyBook.odm.

Is there any way to make these commands permanent, so I don't have to enter them every time I restart Terminal?

Thanks in advance and thanks for your script!

Chris


At this point, if calling overdrive produces the error message -bash: overdrive: command not found, you'll need to add ~/.local/bin to your PATH. One way to do this:

printf 'export PATH=$HOME/.local/bin:$PATH\n' >> ~/.bashrc
source ~/.bashrc

Libraries omitting ODM download links

It seems like OverDrive is moving away from allowing access ODM files. One particular library I use no longer has an option to download them from their site.

Is there a way to get access to the ODM data from the audiobook ID? e.g. XXXX.listen.overdrive.com?

Deprecate tidy

Try to find an alternative to tidy.

It's only used in one place, in the extract_metadata function, to sanitize the metadata XML.

macOS comes with an old version (2006-10-31) of tidy:

/usr/bin/tidy -v

HTML Tidy for Mac OS X released on 31 October 2006 - Apple Inc. build 16.4

so for the most part it does work, but tidy is finicky and opinionated and not exactly stable.

Feature Request: download epubs

There are two types of epubs available for download. The least common type is the "Open EPUB", but it should be easy to implement, since it's a direct download with no DRM.

The second type downloads an ACSM file which you have to open with Adobe Digital Editions to download the encrypted EPUB. Debugging the network traffic, it looks to be relatively straightforward. ADE makes a post request using the info in the ACSM file, and gets another XML file in return, which contains the download link. I might be missing something, as I found a project that makes it sound a bit more complicated: http://indefero.soutade.fr/p/libgourou/ .
Once the encrypted epub is downloaded, the user can use DeDRM to strip the DRM.

Permission denied when trying to install on Mac

Hello! When I try to starting the installation process using the

curl https://chbrown.github.io/overdrive/overdrive.sh > /usr/local/bin/overdrive
chmod +x /usr/local/bin/overdrive

in my Mac terminal, it tells me that permission is denied. How can I fix this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.