1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
{ pkgs, depot, ... }:

let
  inherit (depot.nix) writeExecline getBins;

  bins = getBins pkgs.coreutils [ "split" "mktemp" "rm" "rmdir" ]
      // getBins pkgs.lr      [ "lr" ]
      // getBins pkgs.xe      [ "xe" ]
      // getBins pkgs.qrencode [ "qrencode" ]
      // getBins pkgs.zbar    [ "zbarimg" ]
      // getBins pkgs.sane-backends [ "scanimg" ];

  qr-code-props = {
    # second highest redundancy level
    level = "Q";
    # max amount of bytes that level Q can encode
    bytes = "1700";
  };

  # Takes a private GPG key encoded with paperkey on stdin
  # and execs into the argv for each qr code image (on stdin).
  print-qr-codes = writeExecline "print-qr-codes" {} [
    split-stdin
    "pipeline" [
      bins.qrencode
      "--level=${qr-code-props.level}"
      "--dpi=300"
      "-o-"
    ]
    "$@"
  ];

  split-stdin = pkgs.writers.writePython3 "split-stdin" {} ''
    import sys
    import subprocess

    while True:
        str = sys.stdin.buffer.read(${qr-code-props.bytes})
        if str == "":
            break
        ret = subprocess.run(sys.argv[1:], input=str)
        code = ret.returncode
        if code != 0:
            sys.exit(code if code > 0 else 128 - code)
  '';

# scanning:
# for i in (seq 0 9); scanimage --device=\'fujitsu:ScanSnap iX500:1527308\' --mode=gray --resolution=100 --format=png | zbarimg -Sdisable -Sqrcode.enable --raw - | head --bytes=-1; end > out

in {
  inherit print-qr-codes;
}