diff options
Diffstat (limited to 'pkgs/games')
-rw-r--r-- | pkgs/games/gog/default.nix | 1 | ||||
-rw-r--r-- | pkgs/games/gog/fetch-gog/default.nix | 29 | ||||
-rw-r--r-- | pkgs/games/gog/kingdoms-and-castles.nix | 14 | ||||
-rw-r--r-- | pkgs/games/humblebundle/fetch-humble-bundle/default.nix | 89 | ||||
-rw-r--r-- | pkgs/games/humblebundle/fetch-humble-bundle/guard-code.patch | 121 |
5 files changed, 230 insertions, 24 deletions
diff --git a/pkgs/games/gog/default.nix b/pkgs/games/gog/default.nix index 6588d6f2..f1010a00 100644 --- a/pkgs/games/gog/default.nix +++ b/pkgs/games/gog/default.nix @@ -16,6 +16,7 @@ let dungeons3 = callPackage ./dungeons3.nix {}; epistory = callPackage ./epistory.nix { }; homm3 = callPackage ./homm3 {}; + kingdoms-and-castles = callPackage ./kingdoms-and-castles.nix {}; overload = callPackage ./overload.nix {}; party-hard = callPackage ./party-hard.nix {}; satellite-reign = callPackage ./satellite-reign.nix {}; diff --git a/pkgs/games/gog/fetch-gog/default.nix b/pkgs/games/gog/fetch-gog/default.nix index d4a35a05..c1d350ce 100644 --- a/pkgs/games/gog/fetch-gog/default.nix +++ b/pkgs/games/gog/fetch-gog/default.nix @@ -147,14 +147,24 @@ let } ''; - in runCommandCC "get-captcha" { - nativeBuildInputs = [ pkgconfig ]; + in stdenv.mkDerivation { + name = "get-captcha"; + + dontUnpack = true; + + nativeBuildInputs = [ pkgconfig (qt5.wrapQtAppsHook or null) ]; buildInputs = [ qt5.qtbase qt5.qtwebengine ]; preferLocalBuild = true; - } '' - g++ $(pkg-config --libs --cflags Qt5WebEngineWidgets Qt5WebEngine) \ - -Wall -std=c++11 -o "$out" ${application} - ''; + + buildPhase = '' + g++ $(pkg-config --libs --cflags Qt5WebEngineWidgets Qt5WebEngine) \ + -Wall -std=c++11 -o get-captcha ${application} + ''; + + installPhase = '' + install -vD get-captcha "$out/bin/get-captcha" + ''; + }; mkPyStr = str: "'${stdenv.lib.escape ["'" "\\"] (toString str)}'"; @@ -178,7 +188,7 @@ let def login(self): browser = mechanicalsoup.StatefulBrowser() response = browser.open(${mkPyStr authURL}) - if "google.com/recaptcha" in response.text: + if "https://www.recaptcha.net/recaptcha" in response.text: token_url = self.login_with_captcha() else: browser.select_form('form[name="login"]') @@ -190,7 +200,7 @@ let if 'code' not in query: sys.stderr.write( - "Unable to login with the provided GOG credentials." + "Unable to login with the provided GOG credentials.\n" ) raise SystemExit(1) @@ -210,7 +220,8 @@ let def login_with_captcha(self): sys.stderr.write("Solving a captcha is required to log in.\n") - sys.stderr.write("Please run " ${mkPyStr getCaptcha} " now.\n") + sys.stderr.write("Please run " ${mkPyStr getCaptcha} + "/bin/get-captcha now.\n") sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sys.stderr.write("Waiting for connection") i = 0 diff --git a/pkgs/games/gog/kingdoms-and-castles.nix b/pkgs/games/gog/kingdoms-and-castles.nix new file mode 100644 index 00000000..e31551cc --- /dev/null +++ b/pkgs/games/gog/kingdoms-and-castles.nix @@ -0,0 +1,14 @@ +{ buildUnity, fetchGog }: + +buildUnity { + name = "kingdoms-and-castles"; + fullName = "KingdomsAndCastles"; + saveDir = "LionShield/Kingdoms and Castles"; + version = "115r12"; + + src = fetchGog { + productId = 2067763543; + downloadName = "en3installer0"; + sha256 = "1ag03piq09z7hljcbs145hyj8z0gjcvffj99znf3mnbw2qipb7pq"; + }; +} diff --git a/pkgs/games/humblebundle/fetch-humble-bundle/default.nix b/pkgs/games/humblebundle/fetch-humble-bundle/default.nix index f6f161dc..1340bce8 100644 --- a/pkgs/games/humblebundle/fetch-humble-bundle/default.nix +++ b/pkgs/games/humblebundle/fetch-humble-bundle/default.nix @@ -1,13 +1,20 @@ -{ stdenv, curl, cacert, writeText, fetchFromGitHub, fetchpatch -, python, pythonPackages +{ stdenv, curl, cacert, writeText, writeScript, fetchFromGitHub, fetchpatch +, python, python3, pythonPackages # Dependencies for the captcha solver -, pkgconfig, qt5, runCommandCC +, pkgconfig, qt5 , email, password }: -{ name ? null, machineName, downloadName ? "Download", suffix ? "humblebundle", md5 }: let +{ name ? null +, machineName +, downloadName ? "Download" +, suffix ? "humblebundle" +, md5 +}: + +let cafile = "${cacert}/etc/ssl/certs/ca-bundle.crt"; getCaptcha = let @@ -77,13 +84,34 @@ } ''; - in runCommandCC "get-captcha" { - nativeBuildInputs = [ pkgconfig ]; + in stdenv.mkDerivation { + name = "get-captcha"; + + dontUnpack = true; + + nativeBuildInputs = [ pkgconfig (qt5.wrapQtAppsHook or null) ]; buildInputs = [ qt5.qtbase qt5.qtwebengine ]; preferLocalBuild = true; - } '' - g++ $(pkg-config --libs --cflags Qt5WebEngineWidgets Qt5WebEngine) \ - -Wall -std=c++11 -o "$out" ${application} + + buildPhase = '' + g++ $(pkg-config --libs --cflags Qt5WebEngineWidgets Qt5WebEngine) \ + -Wall -std=c++11 -o get-captcha ${application} + ''; + + installPhase = '' + install -vD get-captcha "$out/bin/get-captcha" + ''; + }; + + getGuard = writeScript "get-guard" '' + #!${python3.interpreter} + import socket + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + sock.bind(('localhost', 18129)) + sock.listen(1) + with sock.accept()[0] as conn: + guard = input("Guard code: ") + conn.sendall(guard.encode()) ''; humbleAPI = pythonPackages.buildPythonPackage rec { @@ -97,6 +125,8 @@ sha256 = "1kcg42nh7sbjabim1pbqx14468pypznjy7fx2bv7dicy0sqd9b8j"; }; + patches = [ ./guard-code.patch ]; + postPatch = '' sed -i -e '/^LOGIN_URL *=/s,/login,/processlogin,' humblebundle/client.py sed -i -e '/self\.supports_canonical.*data.*supports_canonical/d' \ @@ -138,7 +168,8 @@ def login_with_captcha(hb): print >>sys.stderr, "Solving a captcha is required to log in." - print >>sys.stderr, "Please run " ${pyStr (toString getCaptcha)} " now." + print >>sys.stderr, "Please run " ${pyStr (toString getCaptcha)} \ + "/bin/get-captcha now." sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print >>sys.stderr, "Waiting for connection", i = 0 @@ -153,13 +184,41 @@ response = sock.recv(4096) sock.close() print >>sys.stderr, "Captcha solved correctly, logging in." - hb.login(${pyStr email}, ${pyStr password}, recaptcha_response=response) + api_login(hb, recaptcha_response=response) + + def login_with_guard(hb, skip_code): + print >>sys.stderr, "A guard code has been sent to your email address." + print >>sys.stderr, "Please run " ${pyStr (toString getGuard)} " now." + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + print >>sys.stderr, "Waiting for connection", + # XXX: DRY! + i = 0 + while sock.connect_ex(("127.0.0.1", 18129)) != 0: + time.sleep(0.1) + if i % 10 == 0: + sys.stderr.write('.') + sys.stderr.flush() + i += 1 + print >>sys.stderr, " connected." + print >>sys.stderr, "Waiting for guard code..." + response = sock.recv(4096) + sock.close() + print >>sys.stderr, "Guard code supplied, logging in." + api_login(hb, captcha_skip_code=skip_code, guard_code=response) + + def api_login(hb, recaptcha_response=None, + captcha_skip_code=None, guard_code=None): + try: + hb.login(${pyStr email}, ${pyStr password}, + recaptcha_response=recaptcha_response, + captcha_skip_code=captcha_skip_code, guard_code=guard_code) + except humblebundle.exceptions.HumbleCaptchaException: + login_with_captcha(hb) + except humblebundle.exceptions.HumbleGuardRequiredException as e: + login_with_guard(hb, e.captcha_skip_code) hb = humblebundle.HumbleApi() - try: - hb.login(${pyStr email}, ${pyStr password}) - except humblebundle.exceptions.HumbleCaptchaException: - login_with_captcha(hb) + api_login(hb) products = dict(get_products(hb)) dstruct = find_download(products) diff --git a/pkgs/games/humblebundle/fetch-humble-bundle/guard-code.patch b/pkgs/games/humblebundle/fetch-humble-bundle/guard-code.patch new file mode 100644 index 00000000..f17928ae --- /dev/null +++ b/pkgs/games/humblebundle/fetch-humble-bundle/guard-code.patch @@ -0,0 +1,121 @@ +diff --git a/humblebundle/client.py b/humblebundle/client.py +index fbc31c9..44184a1 100644 +--- a/humblebundle/client.py ++++ b/humblebundle/client.py +@@ -75,7 +75,9 @@ class HumbleApi(object): + """ + + @callback +- def login(self, username, password, authy_token=None, recaptcha_challenge=None, recaptcha_response=None, ++ def login(self, username, password, authy_token=None, ++ recaptcha_challenge=None, recaptcha_response=None, ++ guard_code=None, captcha_skip_code=None, + *args, **kwargs): + """ + Login to the Humble Bundle API. The response sets the _simpleauth_sess cookie which is stored in the session +@@ -87,6 +89,8 @@ class HumbleApi(object): + :type authy_token: integer or str + :param str recaptcha_challenge: (optional) The challenge signed by Humble Bundle's public key from reCAPTCHA + :param str recaptcha_response: (optional) The plaintext solved CAPTCHA ++ :param str guard_code: (optional) The guard code sent via email ++ :param str captcha_skip_code: (optional) A token to skip the CAPTCHA + :param list args: (optional) Extra positional args to pass to the request + :param dict kwargs: (optional) Extra keyword args to pass to the request. If a data dict is supplied a key + collision with any of the above params will resolved in favor of the supplied param +@@ -108,7 +112,9 @@ class HumbleApi(object): + 'password': password, + 'authy-token': authy_token, + 'recaptcha_challenge_field': recaptcha_challenge, +- 'recaptcha_response_field': recaptcha_response} ++ 'recaptcha_response_field': recaptcha_response, ++ 'guard': guard_code, ++ 'captcha-skip-code': captcha_skip_code} + kwargs.setdefault('data', {}).update({k: v for k, v in default_data.items() if v is not None}) + + response = self._request('POST', LOGIN_URL, *args, **kwargs) +diff --git a/humblebundle/exceptions.py b/humblebundle/exceptions.py +index 9041219..fe4eeaf 100644 +--- a/humblebundle/exceptions.py ++++ b/humblebundle/exceptions.py +@@ -9,7 +9,7 @@ __copyright__ = "Copyright 2014, Joel Pedraza" + __license__ = "MIT" + + __all__ = ['HumbleException', 'HumbleResponseException', 'HumbleAuthenticationException', 'HumbleCredentialException', +- 'HumbleCaptchaException', 'HumbleTwoFactorException', 'HumbleParseException'] ++ 'HumbleCaptchaException', 'HumbleTwoFactorException', 'HumbleGuardRequiredException', 'HumbleParseException'] + + from requests import RequestException + +@@ -38,6 +38,7 @@ class HumbleAuthenticationException(HumbleResponseException): + def __init__(self, *args, **kwargs): + self.captcha_required = kwargs.pop('captcha_required', None) + self.authy_required = kwargs.pop('authy_required', None) ++ self.captcha_skip_code = kwargs.pop('captcha_skip_code', None) + super(HumbleAuthenticationException, self).__init__(*args, **kwargs) + + +@@ -62,6 +63,13 @@ class HumbleTwoFactorException(HumbleAuthenticationException): + pass + + ++class HumbleGuardRequiredException(HumbleAuthenticationException): ++ """ ++ A guard code is required ++ """ ++ pass ++ ++ + class HumbleParseException(HumbleResponseException): + """ + An error occurred while parsing +diff --git a/humblebundle/handlers.py b/humblebundle/handlers.py +index 36fc6e1..a8acebf 100644 +--- a/humblebundle/handlers.py ++++ b/humblebundle/handlers.py +@@ -64,29 +64,42 @@ def login_handler(client, response): + success = data.get('success', None) + if success is True: + return True ++ if data.get('goto', None) is not None: ++ return True + + captcha_required = data.get('captcha_required') + authy_required = data.get('authy_required') ++ captcha_skip_code = data.get('skip_code', [None])[0] ++ ++ guard = data.get('humble_guard_required', False) ++ if guard: ++ raise HumbleGuardRequiredException('Guard code required', request=response.request, response=response, ++ captcha_required=captcha_required, authy_required=authy_required, ++ captcha_skip_code=captcha_skip_code) + + errors, error_msg = get_errors(data) + if errors: + captcha = errors.get('captcha') + if captcha: + raise HumbleCaptchaException(error_msg, request=response.request, response=response, +- captcha_required=captcha_required, authy_required=authy_required) ++ captcha_required=captcha_required, authy_required=authy_required, ++ captcha_skip_code=captcha_skip_code) + + username = errors.get('username') + if username: + raise HumbleCredentialException(error_msg, request=response.request, response=response, +- captcha_required=captcha_required, authy_required=authy_required) ++ captcha_required=captcha_required, authy_required=authy_required, ++ captcha_skip_code=captcha_skip_code) + + authy_token = errors.get("authy-token") + if authy_token: + raise HumbleTwoFactorException(error_msg, request=response.request, response=response, +- captcha_required=captcha_required, authy_required=authy_required) ++ captcha_required=captcha_required, authy_required=authy_required, ++ captcha_skip_code=captcha_skip_code) + + raise HumbleAuthenticationException(error_msg, request=response.request, response=response, +- captcha_required=captcha_required, authy_required=authy_required) ++ captcha_required=captcha_required, authy_required=authy_required, ++ captcha_skip_code=captcha_skip_code) + + + def gamekeys_handler(client, response): |