diff --git a/scripts/yt-block/a.out b/scripts/yt-block/a.out new file mode 100755 index 0000000..a6ce3da Binary files /dev/null and b/scripts/yt-block/a.out differ diff --git a/scripts/yt-block/app.nix b/scripts/yt-block/app.nix new file mode 100644 index 0000000..a62c0d3 --- /dev/null +++ b/scripts/yt-block/app.nix @@ -0,0 +1,11 @@ +{ pkgs +, ... +}: let + python = pkgs.python3.withPackages (ps: with ps; [pkgs.python311Pacakges.cryptography]); + python_script = pkgs.writeText (builtins.readFile ./main.py); +in pkgs.writeShellApplication { + name = "yt-block"; + text = '' + ${python}/bin/python ${python_script} + ''; +} diff --git a/scripts/yt-block/main.py b/scripts/yt-block/main.py new file mode 100644 index 0000000..e6e0a5f --- /dev/null +++ b/scripts/yt-block/main.py @@ -0,0 +1,203 @@ + +import hashlib +import datetime +import sys +from cryptography.fernet import Fernet +import os +import json +import base64 +import subprocess + +YT_TIME_MAX = 90 # in min +STATE_FILE = "/etc/yt_block_state" + +DEFAULT_STATE = { + "yt_time_left": 0, + "yt_time_current": 0, + "date": "2024-07-15", +} + +YT_HOSTS = [ + [ "127.0.0.1", "youtube.com" ], + [ "127.0.0.1", "www.youtube.com" ], + [ "::1", "www.youtube.com" ], + [ "::1", "youtube.com" ], +] + +def main(): + if sys.argv[1] == "g" or sys.argv[1] == "guard": + cmd_guard() + return + + if sys.argv[1] == "r" or sys.argv[1] == "request": + cmd_request() + return + + if sys.argv[1] == "i" or sys.argv[1] == "info": + cmd_info() + return + + print("unknown command!!!!") + + +def cmd_guard(): + pwd = get_pwd() + + state = read_state(pwd) + + # if it's after 22:00 block yt and kill all minecraft processes + now = datetime.datetime.now() + if now.hour >= 22: + block_yt() + kill_mc() + + # if date is not today, set time_left to YT_TIME_LIMIT + date_from_state = datetime.datetime.strptime(state["date"], "%Y-%m-%d") + if now.date() != date_from_state.date(): + state["yt_time_left"] = YT_TIME_MAX + state["date"] = now.strftime("%Y-%m-%d") + + + # if time_current in state is 0, block yt + if state["yt_time_current"] == 0: + block_yt() + + # if time_current in state is 0, block yt + if state["yt_time_current"] >= 0: + unblock_yt() + + # decrement time_current + state["yt_time_current"] -= 1 + + write_state(state, pwd) + +def cmd_request(): + pwd = get_pwd() + + state = read_state(pwd) + + time_to_request = int(sys.argv[2]) + + if time_to_request > state["yt_time_left"]: + print("Trying to request more time, than is left") + exit(1) + + state["yt_time_left"] -= time_to_request + state["yt_time_current"] = time_to_request +1 # +1 because we are running guard now as well.... + + write_state(state, pwd) + + # run gurad now as well ... so that changes take effect immediately + cmd_guard() + + +def cmd_info(): + pwd = get_pwd() + + state = read_state(pwd) + + kill_mc() + + print("YouTube") + print("time_left:", state["yt_time_left"]) + print("time_current:", state["yt_time_current"]) + + + + +def get_pwd(): + with open("/etc/machine-id", "r") as f: + pwd = f.read() + + + for i in range(0, 7): + my_string_bits = pwd.encode('utf-8') + secret_thing = hashlib.sha256(my_string_bits) + pwd = secret_thing.hexdigest() + + pwd = pwd[0:32] + pwd_bytes =pwd.encode('ascii') + pwd_base64_bytes = base64.b64encode(pwd_bytes) + return pwd_base64_bytes + + +def read_state(pwd): + fernet = Fernet(pwd) + + if not os.path.exists(STATE_FILE): + with open(STATE_FILE, "wb") as file: + encrypted = fernet.encrypt(json.dumps(DEFAULT_STATE).encode()) + file.write(encrypted) + + return DEFAULT_STATE + + with open(STATE_FILE, "rb") as file: + state_encrypted = file.read() + state_string = fernet.decrypt(state_encrypted) + state = json.loads(state_string) + + return state + + +def write_state(state, pwd): + fernet = Fernet(pwd) + + with open(STATE_FILE, "wb") as file: + state_string = json.dumps(state) + state_encrypted = fernet.encrypt(state_string.encode()) + file.write(state_encrypted) + + +def get_hosts(): + with open(f"/etc/hosts", "r") as file: + hosts = [] + for line in file.readlines(): + if line == "\n": + continue + split = line.split(" ") + try: + hosts.append([split[1].strip(), split[0].strip()]) + except: + print("error with geting hosts from /etc/hosts: ", split) + return hosts + + +def write_hosts(hosts): + with open("/etc/hosts", "w") as file: + lines = [] + for entry in hosts: + lines.append(entry[1] + " " + entry[0]) + + file.write("\n".join(lines) + "\n") + + +def block_yt(): + hosts = get_hosts() + for entry in YT_HOSTS: + hosts.append(entry) + + write_hosts(hosts) + +def unblock_yt(): + hosts = get_hosts() + new_hosts = [] + for entry in hosts: + if entry[0] == "youtube.com" or entry[0] == "www.youtube.com": + continue + else: + new_hosts.append(entry) + + write_hosts(new_hosts) + +def kill_mc(): + output = subprocess.check_output(['bash', '-c', "ps fax | grep minecraft"]) + for line in output.decode().split("\n"): + if line.find("java") != -1: + kill_line(line) + +def kill_line(line): + pid = int(line.split(" ")[1]) + os.system(f"kill {pid}") + +if __name__ == "__main__": + main() diff --git a/scripts/yt-block/module.nix b/scripts/yt-block/module.nix new file mode 100644 index 0000000..3c69ed5 --- /dev/null +++ b/scripts/yt-block/module.nix @@ -0,0 +1,16 @@ +{ pkgs, ... }: +let + yt_block = pkgs.callPackage ./app.nix {}; +in { + systemd.services.yt-block = { + enable = true; + description = "Block Youtube"; + serviceConfig = { + Restart = "always"; + RestartSec = "60s"; + ExecStart = "${yt_block}/bin/yt_block guard"; + }; + wantedBy = [ "multi-user.target" ]; + }; + environment.systemPackages = [ yt_block ]; +}