summaryrefslogtreecommitdiffstats
path: root/lass/3modules/autowifi.nix
blob: 930d9972733d9413cbf4c946eced3f217c5893d3 (plain)
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
{ config, lib, pkgs, ... }:
with import <stockholm/lib>;
let

  cfg = config.lass.autowifi;

in {
  options.lass.autowifi = {
    enable = mkEnableOption "automatic wifi connector";
    knownWifisFile = mkOption {
      type = types.str;
      default = "/etc/wifis";
    };
  };

  config = {
    systemd.services.autowifi = {
      description = "Automatic wifi connector";
      wantedBy = [ "multi-user.target" ];
      serviceConfig = {
        Type = "simple";
        Restart = "always";
        RestartSec = "10s";
        ExecStart = pkgs.writers.writePython3 "autowifi" {} /* python3 */ ''
          import subprocess
          import time
          import urllib.request


          def connect(ssid, psk=None):
              subprocess.run(["${pkgs.networkmanager}/bin/nmcli", "connection", "delete", "autowifi"])
              print("connecting to {}".format(ssid))
              if psk is None:
                  subprocess.run(["${pkgs.networkmanager}/bin/nmcli", "device", "wifi", "connect", ssid, "name", "autowifi"])
              else:
                  subprocess.run(["${pkgs.networkmanager}/bin/nmcli", "device", "wifi", "connect", ssid, "name", "autowifi", "password", psk])


          def scan():
              wifis_raw = subprocess.check_output(["${pkgs.networkmanager}/bin/nmcli", "-t", "device", "wifi", "list", "--rescan", "yes"])
              wifis_list = wifis_raw.split(b'\n')
              wifis = []
              for line in wifis_list:
                  ls = line.split(b':')
                  if len(ls) == 8:
                      wifis.append({"ssid": ls[1], "signal": int(ls[5]), "crypto": ls[7]})
              return wifis


          def get_known_wifis():
              wifis_lines = []
              with open('${cfg.knownWifisFile}') as f:
                  wifis_lines = f.read().splitlines()
              wifis = []
              for line in wifis_lines:
                  ls = line.split(':')
                  wifis.append({"ssid": ls[0].encode(), "psk": ls[1].encode()})
              return wifis


          def check_internet():
              try:
                  beacon = urllib.request.urlopen('http://krebsco.de/secret')
              except:  # noqa
                  print("no internet")
                  return False
              if beacon.read() == b'1337\n':
                  return True
              print("no internet")
              return False


          def is_wifi_open(wifi):
              if wifi['crypto'] == ${"b''"}:
                  return True
              else:
                  return False


          def is_wifi_seen(wifi, seen_wifis):
              for seen_wifi in seen_wifis:
                  if seen_wifi["ssid"] == wifi["ssid"]:
                      return True
              return False


          def bloop():
              while True:
                  if not check_internet():
                      wifis = scan()
                      known_wifis = get_known_wifis()
                      known_seen_wifis = [wifi for wifi in known_wifis if is_wifi_seen(wifi, wifis)]
                      for wifi in known_seen_wifis:
                          connect(wifi['ssid'], wifi['psk'])
                          if check_internet():
                              continue
                      open_wifis = filter(is_wifi_open, wifis)
                      for wifi in open_wifis:
                          connect(wifi['ssid'])
                          if check_internet():
                              continue
                  time.sleep(10)


          bloop()
        '';
      };
    };
  };
}