Fixed #5 & Fixed #9. Added --keys support for downloading a single bundle

This commit is contained in:
Eddy Hintze 2020-01-20 10:26:48 -05:00
parent 7b08f9638b
commit 7dde7f8459
5 changed files with 41 additions and 20 deletions

View File

@ -1,5 +1,12 @@
# Change log
### 0.1.0
- Filename saved is now the original name of the file
- key used in cache is different due to changing the file name (this may result in duplicate downloads if you have run the older version)
- Support for downloading a single Bundle/Purchase by using the flag `-k` or `--key` and getting the key from the url of a purchase
### 0.0.8
- gen-cookies now works with SSO feature and 2FA logins
- Added `--include` & `--exclude` cli args to filter file types

View File

@ -44,10 +44,11 @@ Use the following command to download your Humble Bundle Library:
`hbd download --cookie-file hbd-cookies.txt --library-path "Downloaded Library" --progress`
This directory structure will be used:
`Downloaded Library/Bundle Name/Bundle Item.ext`
`Downloaded Library/Purchase Name/Item Name/downloaded_file.ext`
## Notes
* Inside your library folder a file named `.cache.json` is saved and keeps track of the files that have been downloaded. This way running the download command again pointing to the same directory will only download new or updated files.
* Use `--help` with all `hbd` commands to see available options
* Find supported platforms for the `--platform` flag by visiting your Humble Bundle Library and look under the **Platform** dropdown
* Download select bundles by using the `-k` or `--keys` flag. Find these keys by going to your *Purchases* section, click on a products and there should be a `downloads?key=XXXX` in the url.

View File

@ -1 +1 @@
__version__ = '0.0.8'
__version__ = '0.1.0'

View File

@ -71,6 +71,12 @@ def cli():
type=str, nargs='*',
help="Only download files with these extensions. Ex: -i pdf mobi",
)
parser_download.add_argument(
'-k', '--keys',
type=str, nargs='*',
help=("The purchase download key. Find in the url on the "
"products/bundle download page. Can set multiple"),
)
cli_args = parser.parse_args()
@ -87,4 +93,5 @@ def cli():
ext_include=cli_args.include,
ext_exclude=cli_args.exclude,
platform_include=cli_args.platform,
purchase_keys=cli_args.keys,
)

View File

@ -18,7 +18,8 @@ def _clean_name(dirty_str):
def download_library(cookie_path, library_path, progress_bar=False,
ext_include=None, ext_exclude=None, platform_include=None):
ext_include=None, ext_exclude=None, platform_include=None,
purchase_keys=None):
if ext_include is None:
ext_include = []
ext_include = list(map(str.lower, ext_include))
@ -44,14 +45,16 @@ def download_library(cookie_path, library_path, progress_bar=False,
except FileNotFoundError:
cache_data = {}
library_r = requests.get('https://www.humblebundle.com/home/library',
headers={'cookie': account_cookies})
logger.debug("Library request: " + str(library_r))
library_page = parsel.Selector(text=library_r.text)
orders_json = json.loads(library_page.css('#user-home-json-data')
.xpath('string()').extract_first())
if not purchase_keys:
library_r = requests.get('https://www.humblebundle.com/home/library',
headers={'cookie': account_cookies})
logger.debug("Library request: " + str(library_r))
library_page = parsel.Selector(text=library_r.text)
orders_json = json.loads(library_page.css('#user-home-json-data')
.xpath('string()').extract_first())
purchase_keys = orders_json['gamekeys']
for order_id in orders_json['gamekeys']:
for order_id in purchase_keys:
order_url = 'https://www.humblebundle.com/api/v1/order/{order_id}?all_tpkds=true'.format(order_id=order_id) # noqa: E501
order_r = requests.get(order_url,
headers={'cookie': account_cookies})
@ -88,15 +91,16 @@ def download_library(cookie_path, library_path, progress_bar=False,
+ "/" + item_title)
continue
ext = url.split('?')[0].split('.')[-1]
file_title = item_title + "." + ext
url_filename = url.split('?')[0].split('/')[-1]
cache_file_key = order_id + ':' + url_filename
ext = url_filename.split('.')[-1]
# Only get the file types we care about
if ((ext_include and ext.lower() not in ext_include)
or (ext_exclude and ext.lower() in ext_exclude)):
logger.info("Skipping the file " + file_title)
logger.info("Skipping the file " + url_filename)
continue
filename = os.path.join(item_folder, file_title)
filename = os.path.join(item_folder, url_filename)
item_r = requests.get(url, stream=True)
logger.debug("Item request: {item_r}, Url: {url}"
.format(item_r=item_r, url=url))
@ -108,10 +112,11 @@ def download_library(cookie_path, library_path, progress_bar=False,
'url_etag': item_r.headers['ETag'][1:-1],
'url_crc': item_r.headers['X-HW-Cache-CRC'],
}
if file_info != cache_data.get(filename, {}):
if file_info != cache_data.get(cache_file_key, {}):
if not progress_bar:
logger.info("Downloading: {file_title}"
.format(file_title=file_title))
logger.info("Downloading: {item_title}/{url_filename}"
.format(item_title=item_title,
url_filename=url_filename))
with open(filename, 'wb') as outfile:
total_length = item_r.headers.get('content-length')
@ -126,8 +131,9 @@ def download_library(cookie_path, library_path, progress_bar=False,
pb_width = 50
done = int(pb_width * dl / total_length)
if progress_bar:
print("Downloading: {file_title}: {percent}% [{filler}{space}]" # noqa E501
.format(file_title=file_title,
print("Downloading: {item_title}/{url_filename}: {percent}% [{filler}{space}]" # noqa E501
.format(item_title=item_title,
url_filename=url_filename,
percent=int(done * (100 / pb_width)), # noqa E501
filler='=' * done,
space=' ' * (pb_width - done), # noqa E501
@ -138,7 +144,7 @@ def download_library(cookie_path, library_path, progress_bar=False,
# is on its own line
print()
cache_data[filename] = file_info
cache_data[cache_file_key] = file_info
# Update cache file with newest data so if the script
# quits it can keep track of the progress
with open(cache_file, 'w') as outfile: