Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
34fb8f1
Fix authentication exception not declared
MayeulC Jul 21, 2018
8850cf9
Change two humble_api methods to static methods
MayeulC Jul 21, 2018
10f27e6
add Dockerfile
Strubbl Nov 22, 2018
258e5c2
Improve unit tests
MayeulC May 8, 2018
163fba4
Move project to the humble_downloader subfolder
MayeulC Jun 17, 2018
b1aa791
Fix imports following the renaming
MayeulC Jun 17, 2018
f6baf29
Add codacy coverage support to to .travis.yaml
MayeulC Jun 17, 2018
7190806
Add a setup.py file
MayeulC Jun 17, 2018
9ff2c52
Add dummy content to the test library
MayeulC Jun 17, 2018
236d8cd
Add a humble trove proof-of-concept
MayeulC Jun 17, 2018
0246df6
Add an option to list game keys
MayeulC Jun 18, 2018
46e4dc4
Improve humble trove support: Use a dummy gamekey
MayeulC Jul 21, 2018
7c9707b
Fix tests, improve them, exercise code for the humble trove
MayeulC Jul 21, 2018
a45dbaa
Remove Humble trove proof of concept script
MayeulC Jul 21, 2018
701c9e1
Improve the readme and travis script
MayeulC Jul 21, 2018
953f5c6
Update the list of exceptions exported by the API
MayeulC Sep 16, 2018
98463dc
Import logger in progress_tracker
MayeulC Sep 17, 2018
34679b5
Only add a "keys" option to the list action
MayeulC Sep 17, 2018
cccda3b
Add an option to only display/download a single game key
MayeulC Sep 17, 2018
037a98d
Add humble_downloader exports to the __init__
MayeulC Sep 17, 2018
1d1662e
Fix trove_order URLs during model constuction
MayeulC Sep 17, 2018
67e638d
Ignore file size and md5 checks for trove items
MayeulC Sep 24, 2018
2ea82b8
Download HB Trove games based on configuration file
kidburglar Dec 26, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
language: "python"
python: "3.6"
install:
- pip install requests pyyaml pytest-cov python-coveralls
- pip install requests pyyaml lxml pytest-cov python-coveralls httpretty codacy-coverage
script:
- python3 -m pytest --cov=.
after_success:
- coveralls
- coverage xml
- python-codacy-coverage -r coverage.xml
notifications:
- email: false
12 changes: 12 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM python:3

VOLUME /data
WORKDIR /app

RUN git clone https://github.com/MayeulC/hb-downloader.git /app && \
cd /app && \
git checkout poc-trove && \
python setup.py install

CMD python /app/hb-downloader.py download

6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ library, available at https://github.com/saik0/humblebundle-python
* Python 3.6
* requests library
* pyyaml library
* (optionnally for Humble Trove support) lxml

## Python Installation
Several features particular to Python v3.6 might have been used during the
Expand All @@ -32,12 +33,13 @@ https://www.python.org/downloads/ and grab the latest 3.x.x release.
## Getting the Prerequisites
From a command prompt, enter:

pip install requests
pip install pyyaml
pip install requests pyyaml lxml

You'll either be informed that the requirement is already satisfied, or pip
will retrieve, install, and configure the libraries for you.

Alternatively, you can run the `setup.py` script.

## Getting the Installation Files
Perform one of the following actions:
* Download the zip file from the [releases
Expand Down
55 changes: 7 additions & 48 deletions hb-downloader.py
Original file line number Diff line number Diff line change
@@ -1,53 +1,12 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logger
from config_data import ConfigData
from configuration import Configuration
from event_handler import EventHandler
from humble_api.humble_api import HumbleApi
from actions import Action

__author__ = "Brian Schkerke"
__copyright__ = "Copyright 2016 Brian Schkerke"
__license__ = "MIT"


print("Humble Bundle Downloader v%s" % ConfigData.VERSION)
print("This program is not affiliated nor endorsed by Humble Bundle, Inc.")
print("For any suggestion or bug report, please create an issue at:\n%s" %
ConfigData.BUG_REPORT_URL)
print("")

# Load the configuration from the YAML file...
Configuration.load_configuration("hb-downloader-settings.yaml")
Configuration.parse_command_line()
Configuration.dump_configuration()
Configuration.push_configuration()

validation_status, message = Configuration.validate_configuration()
if not validation_status:
logger.display_message(False, "Error", message)
exit("Invalid configuration. Please check your command line arguments and"
"hb-downloader-settings.yaml.")

# Initialize the event handlers.
EventHandler.initialize()

hapi = HumbleApi(ConfigData.auth_sess_cookie)

if not hapi.check_login():
exit("Login to humblebundle.com failed."
" Please verify your authentication cookie")

logger.display_message(False, "Processing", "Downloading order list.")
game_keys = hapi.get_gamekeys()
logger.display_message(False, "Processing", "%s orders found." %
(len(game_keys)))

if ConfigData.action == "download":
Action.batch_download(hapi, game_keys)
else:
Action.list_downloads(hapi, game_keys)
import sys
import humble_downloader

__author__ = "Mayeul Cantan"
__copyright__ = "Copyright 2018 Mayeul Cantan"
__license__ = "MIT"

exit()
if __name__ == "__main__":
sys.exit(humble_downloader.main())
10 changes: 0 additions & 10 deletions humble_api/exceptions/__init__.py

This file was deleted.

62 changes: 62 additions & 0 deletions humble_downloader/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import humble_downloader.logger as logger
from humble_downloader.config_data import ConfigData
from .configuration import Configuration
from .event_handler import EventHandler
from .humble_api.humble_api import HumbleApi
from .actions import Action

__author__ = "Brian Schkerke"
__copyright__ = "Copyright 2016 Brian Schkerke"
__license__ = "MIT"

__all__ = ["ConfigData", "Action", "display_message", "HumbleDownload", "ProgressTracker"]


def main():
print("Humble Bundle Downloader v%s" % ConfigData.VERSION)
print("This program is not affiliated nor endorsed by Humble Bundle, Inc.")
print("For any suggestion or bug report, please create an issue at:\n%s" %
ConfigData.BUG_REPORT_URL)
print("")

# Load the configuration from the YAML file...
Configuration.load_configuration("hb-downloader-settings.yaml")
Configuration.parse_command_line()
Configuration.dump_configuration()
Configuration.push_configuration()

validation_status, message = Configuration.validate_configuration()
if not validation_status:
logger.display_message(False, "Error", message)
sys.exit("Invalid configuration. Please check your command line "
"arguments and hb-downloader-settings.yaml.")

# Initialize the event handlers.
EventHandler.initialize()

hapi = HumbleApi(ConfigData.auth_sess_cookie)

if not hapi.check_login():
exit("Login to humblebundle.com failed."
" Please verify your authentication cookie")

logger.display_message(False, "Processing", "Downloading order list.")
if ConfigData.restrict_keys:
game_keys = ConfigData.restrict_keys
else:
game_keys = hapi.get_gamekeys()
logger.display_message(False, "Processing", "%s orders found." %
(len(game_keys)))

if ConfigData.action == "download":
Action.batch_download(hapi, game_keys)
else:
Action.list_downloads(hapi, game_keys)


if __name__ == "__main__":
sys.exit(main())
15 changes: 10 additions & 5 deletions actions.py → humble_downloader/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@

__license__ = "MIT"

from humble_download import HumbleDownload
from progress_tracker import ProgressTracker
from config_data import ConfigData
import logger
from .humble_download import HumbleDownload
from .progress_tracker import ProgressTracker
from .config_data import ConfigData
from . import logger


class Action:
@staticmethod
def list_downloads(hapi, game_keys):
for key in game_keys:
if ConfigData.download_platforms.get("humble-keys", False):
print("%s" % key)
continue
selector_matched_key_once = False
current_order = hapi.get_order(key)
if 'subproducts' not in current_order:
continue

for current_subproduct in current_order.subproducts or []:
selector_matched_subproduct_once = False
Expand Down Expand Up @@ -66,7 +71,7 @@ def batch_download(hapi, game_keys):
key)
item_count_total += len(humble_downloads)
download_size_total += sum(
dl.humble_file_size for dl in humble_downloads)
dl.humble_file_size or 0 for dl in humble_downloads)
logger.display_message(False, "Processing",
"Added %d downloads for order %s"
% (len(humble_downloads), key))
Expand Down
File renamed without changes.
43 changes: 26 additions & 17 deletions configuration.py → humble_downloader/configuration.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import argparse
import os
import yaml
import logger
from config_data import ConfigData
from humble_api.humble_hash import HumbleHash
from . import logger
from .config_data import ConfigData
from .humble_api.humble_hash import HumbleHash
from .humble_api.humble_api import HumbleApi

__author__ = "Brian Schkerke"
__copyright__ = "Copyright 2016 Brian Schkerke"
Expand Down Expand Up @@ -45,7 +47,6 @@ def load_configuration(config_file):
"""
with open(config_file, "r") as f:
saved_config = yaml.safe_load(f)

ConfigData.download_platforms = saved_config.get(
"download-platforms", ConfigData.download_platforms)
ConfigData.write_md5 = saved_config.get(
Expand Down Expand Up @@ -112,19 +113,27 @@ def parse_command_line():
"parameters are specified, this will default to "
"downloading everything in the library."))

a_list.add_argument(
"-u", "--print-url", action="store_true", dest="print_url",
help=("Print the download url with the output. Please note "
"that the url expires after a while"))

for action in [a_list, a_download]:
item_type = action.add_subparsers(title="type", dest="item_type")
games = item_type.add_parser("games")
games = item_type.add_parser("games", help="Only list games")
games.add_argument(
"--platform", nargs='+', choices=[ # TODO: add NATIVE?
"linux", "mac", "windows", "android", "asmjs"])
item_type.add_parser("ebooks")
item_type.add_parser("audio")
item_type.add_parser("ebooks", help="Only list ebooks")
item_type.add_parser("audio", help="Only display audio products")
if action is a_list:
item_type.add_parser("humble-keys", help=(
"Only list humble bundle keys that identify each "
"purchase"))
action.add_argument("-k", "--keys", nargs="+", help=(
"Only consider listed game key(s). Humble trove games are "
'considered a special "' + HumbleApi.TROVE_GAMEKEY + '" key'))

a_list.add_argument(
"-u", "--print-url", action="store_true", dest="print_url",
help=("Print the download url with the output. Please note "
"that the url expires after a while"))
args = parser.parse_args()

Configuration.configure_action(args)
Expand All @@ -143,20 +152,20 @@ def configure_action(args):
args.print_url = False

if args.action is not None:
if args.platform is None:
args.platform = Configuration.cmdline_platform.get(
args.item_type)
for platform in ConfigData.download_platforms:
if args.platform is None:
ConfigData.download_platforms[platform] = True
continue
if platform in args.platform:
ConfigData.download_platforms[platform] = True
else:
ConfigData.download_platforms[platform] = False
# "fake platforms" can be defined to list info like humble keys
# TODO: only allow them for listing?
if args.item_type not in ConfigData.download_platforms:
ConfigData.download_platforms[args.item_type] = True
else:
args.action = "download"

ConfigData.action = args.action
ConfigData.restrict_keys = args.keys
ConfigData.print_url = args.print_url

@staticmethod
Expand Down
5 changes: 3 additions & 2 deletions event_handler.py → humble_downloader/event_handler.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import logger
from humble_api.events import Events
from . import logger
from .humble_api.events import Events

__author__ = "Brian Schkerke"
__copyright__ = "Copyright 2016 Brian Schkerke"
Expand Down
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions humble_downloader/humble_api/exceptions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

__author__ = "Joel Pedraza"
__copyright__ = "Copyright 2014, Joel Pedraza"
__license__ = "MIT"

__all__ = ["HumbleAuthenticationException", "HumbleDownloadNeededException", "HumbleException", "HumbleParseException",
"HumbleResponseException"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from .humble_response_exception import HumbleResponseException

__license__ = "MIT"


class HumbleAuthenticationException(HumbleResponseException):
"""
Authentication failed due to a rejected authentication cookie
"""

def __init__(self, *args, **kwargs):
"""
Parameterized constructor for the HumbleAuthenticationException.
:param list args: (optional) Extra positional args to pass to the request.
:param dict kwargs: (optional) Extra keyword args to pass to the request.
"""

super(HumbleAuthenticationException, self).__init__(*args, **kwargs)
Loading