about summary refs log tree commit diff
path: root/pkgs/games/humblebundle/fetch-humble-bundle/default.nix
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/games/humblebundle/fetch-humble-bundle/default.nix')
-rw-r--r--pkgs/games/humblebundle/fetch-humble-bundle/default.nix89
1 files changed, 74 insertions, 15 deletions
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)