Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
3091bfd4ff
|
|||
| 0871a319f5 | |||
| 7d723eeb0d | |||
| 9e67d1bd6f | |||
|
911063041f
|
|||
|
7b816ec6a7
|
@@ -57,7 +57,15 @@
|
|||||||
mkVm = name: mkApp "${self.nixosConfigurations.${name}.config.system.build.vm}/bin/run-nixos-vm";
|
mkVm = name: mkApp "${self.nixosConfigurations.${name}.config.system.build.vm}/bin/run-nixos-vm";
|
||||||
in {
|
in {
|
||||||
default = self.apps.${system}.worblehat;
|
default = self.apps.${system}.worblehat;
|
||||||
worblehat = mkApp (lib.getExe self.packages.${system}.worblehat) "Run worblehat without any setup";
|
worblehat = let
|
||||||
|
app = pkgs.writeShellApplication {
|
||||||
|
name = "worblehat-with-default-config";
|
||||||
|
runtimeInputs = [ self.packages.${system}.worblehat ];
|
||||||
|
text = ''
|
||||||
|
worblehat -c ${./config-template.toml} "$@"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in mkApp (lib.getExe app) "Run the worblehat cli with its default config against an SQLite database";
|
||||||
vm = mkVm "vm" "Start a NixOS VM with worblehat installed in kiosk-mode";
|
vm = mkVm "vm" "Start a NixOS VM with worblehat installed in kiosk-mode";
|
||||||
vm-non-kiosk = mkVm "vm-non-kiosk" "Start a NixOS VM with worblehat installed in nonkiosk-mode";
|
vm-non-kiosk = mkVm "vm-non-kiosk" "Start a NixOS VM with worblehat installed in nonkiosk-mode";
|
||||||
});
|
});
|
||||||
|
|||||||
+76
-19
@@ -54,10 +54,43 @@ in {
|
|||||||
freeformType = format.type;
|
freeformType = format.type;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
deadline-daemon = {
|
||||||
|
enable = lib.mkEnableOption "" // {
|
||||||
|
description = ''
|
||||||
|
Whether to enable the worblehat deadline-daemon service,
|
||||||
|
which periodically checks for upcoming deadlines and notifies users.
|
||||||
|
|
||||||
|
Note that this service is independent of the main worblehat service,
|
||||||
|
and must be enabled separately.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
onCalendar = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
How often to trigger rendering the map,
|
||||||
|
in the format of a systemd timer onCalendar configuration.
|
||||||
|
|
||||||
|
See {manpage}`systemd.timer(5)`.
|
||||||
|
'';
|
||||||
|
default = "*-*-* 10:15:00";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkMerge [
|
||||||
|
(lib.mkIf (cfg.enable || cfg.deadline-daemon.enable) {
|
||||||
|
environment.etc."worblehat/config.toml".source = format.generate "worblehat-config.toml" cfg.settings;
|
||||||
|
|
||||||
|
users = {
|
||||||
|
users.worblehat = {
|
||||||
|
group = "worblehat";
|
||||||
|
isNormalUser = true;
|
||||||
|
};
|
||||||
|
groups.worblehat = { };
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable (lib.mkMerge [
|
|
||||||
{
|
|
||||||
services.worblehat.settings = lib.pipe ../config-template.toml [
|
services.worblehat.settings = lib.pipe ../config-template.toml [
|
||||||
builtins.readFile
|
builtins.readFile
|
||||||
builtins.fromTOML
|
builtins.fromTOML
|
||||||
@@ -69,20 +102,12 @@ in {
|
|||||||
})
|
})
|
||||||
(lib.mapAttrsRecursive (_: lib.mkDefault))
|
(lib.mapAttrsRecursive (_: lib.mkDefault))
|
||||||
];
|
];
|
||||||
}
|
})
|
||||||
|
|
||||||
|
(lib.mkIf cfg.enable (lib.mkMerge [
|
||||||
{
|
{
|
||||||
environment.systemPackages = [ cfg.package ];
|
environment.systemPackages = [ cfg.package ];
|
||||||
|
|
||||||
environment.etc."worblehat/config.toml".source = format.generate "worblehat-config.toml" cfg.settings;
|
|
||||||
|
|
||||||
users = {
|
|
||||||
users.worblehat = {
|
|
||||||
group = "worblehat";
|
|
||||||
isNormalUser = true;
|
|
||||||
};
|
|
||||||
groups.worblehat = { };
|
|
||||||
};
|
|
||||||
|
|
||||||
services.worblehat.settings.database.type = "postgresql";
|
services.worblehat.settings.database.type = "postgresql";
|
||||||
services.worblehat.settings.database.postgresql = {
|
services.worblehat.settings.database.postgresql = {
|
||||||
host = "/run/postgresql";
|
host = "/run/postgresql";
|
||||||
@@ -122,7 +147,7 @@ in {
|
|||||||
|
|
||||||
users.users.worblehat = {
|
users.users.worblehat = {
|
||||||
extraGroups = [ "lp" ];
|
extraGroups = [ "lp" ];
|
||||||
shell = (pkgs.writeShellScriptBin "login-shell" "${lib.getExe cfg.screenPackage} -x worblehat") // {
|
shell = (pkgs.writeShellScriptBin "login-shell" "${lib.getExe' cfg.screenPackage "screen"} -x worblehat") // {
|
||||||
shellPath = "/bin/login-shell";
|
shellPath = "/bin/login-shell";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -153,7 +178,7 @@ in {
|
|||||||
User = "worblehat";
|
User = "worblehat";
|
||||||
Group = "worblehat";
|
Group = "worblehat";
|
||||||
|
|
||||||
ExecStartPre = "-${lib.getExe cfg.screenPackage} -X -S worblehat kill";
|
ExecStartPre = "-${lib.getExe' cfg.screenPackage "screen"} -X -S worblehat kill";
|
||||||
ExecStart = let
|
ExecStart = let
|
||||||
screenArgs = lib.escapeShellArgs [
|
screenArgs = lib.escapeShellArgs [
|
||||||
# -dm creates the screen in detached mode without accessing it
|
# -dm creates the screen in detached mode without accessing it
|
||||||
@@ -174,18 +199,50 @@ in {
|
|||||||
config = "/etc/worblehat/config.toml";
|
config = "/etc/worblehat/config.toml";
|
||||||
};
|
};
|
||||||
|
|
||||||
in "${lib.getExe cfg.screenPackage} ${screenArgs} ${lib.getExe cfg.package} ${worblehatArgs} cli";
|
in "${lib.getExe' cfg.screenPackage "screen"} ${screenArgs} ${lib.getExe cfg.package} ${worblehatArgs} cli";
|
||||||
ExecStartPost =
|
ExecStartPost =
|
||||||
lib.optionals (cfg.limitScreenWidth != null) [
|
lib.optionals (cfg.limitScreenWidth != null) [
|
||||||
"${lib.getExe cfg.screenPackage} -X -S worblehat width ${toString cfg.limitScreenWidth}"
|
"${lib.getExe' cfg.screenPackage "screen"} -X -S worblehat width ${toString cfg.limitScreenWidth}"
|
||||||
]
|
]
|
||||||
++ lib.optionals (cfg.limitScreenHeight != null) [
|
++ lib.optionals (cfg.limitScreenHeight != null) [
|
||||||
"${lib.getExe cfg.screenPackage} -X -S worblehat height ${toString cfg.limitScreenHeight}"
|
"${lib.getExe' cfg.screenPackage "screen"} -X -S worblehat height ${toString cfg.limitScreenHeight}"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.getty.autologinUser = "worblehat";
|
services.getty.autologinUser = "worblehat";
|
||||||
})
|
})
|
||||||
]);
|
]))
|
||||||
|
|
||||||
|
(lib.mkIf cfg.deadline-daemon.enable {
|
||||||
|
systemd.timers.worblehat-deadline-daemon = {
|
||||||
|
description = "Worblehat Deadline Daemon";
|
||||||
|
wantedBy = [ "timers.target" ];
|
||||||
|
timerConfig = {
|
||||||
|
OnCalendar = cfg.deadline-daemon.onCalendar;
|
||||||
|
Persistent = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.worblehat-deadline-daemon = {
|
||||||
|
description = "Worblehat Deadline Daemon";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
CPUSchedulingPolicy = "idle";
|
||||||
|
IOSchedulingClass = "idle";
|
||||||
|
|
||||||
|
ExecStart = let
|
||||||
|
worblehatArgs = lib.cli.toCommandLineShellGNU { } {
|
||||||
|
config = "/etc/worblehat/config.toml";
|
||||||
|
};
|
||||||
|
in "${lib.getExe cfg.package} ${worblehatArgs} deadline-daemon";
|
||||||
|
|
||||||
|
User = "worblehat";
|
||||||
|
Group = "worblehat";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ nixpkgs.lib.nixosSystem {
|
|||||||
services.worblehat = {
|
services.worblehat = {
|
||||||
enable = true;
|
enable = true;
|
||||||
createLocalDatabase = true;
|
createLocalDatabase = true;
|
||||||
|
deadline-daemon.enable = true;
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ nixpkgs.lib.nixosSystem {
|
|||||||
DEBUG = true;
|
DEBUG = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
deadline-daemon.enable = true;
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|||||||
+3
-3
@@ -7,10 +7,10 @@ license = { file = "LICENSE" }
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alembic>=1.17",
|
"alembic>=1.16",
|
||||||
"beautifulsoup4>=4.14",
|
"beautifulsoup4>=4.14",
|
||||||
"click>=8.3",
|
"click>=8.2",
|
||||||
"flask-admin>=2.0",
|
"flask-admin>=1.6",
|
||||||
"flask-sqlalchemy>=3.1",
|
"flask-sqlalchemy>=3.1",
|
||||||
"flask>=3.0",
|
"flask>=3.0",
|
||||||
"isbnlib>=3.10",
|
"isbnlib>=3.10",
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ class WorblehatCli(NumberedCmd):
|
|||||||
)
|
)
|
||||||
bookcase_selector.cmdloop()
|
bookcase_selector.cmdloop()
|
||||||
bookcase = bookcase_selector.result
|
bookcase = bookcase_selector.result
|
||||||
|
if bookcase == None:
|
||||||
|
return
|
||||||
|
|
||||||
for shelf in bookcase.shelfs:
|
for shelf in bookcase.shelfs:
|
||||||
print(shelf.short_str())
|
print(shelf.short_str())
|
||||||
@@ -138,6 +140,8 @@ class WorblehatCli(NumberedCmd):
|
|||||||
)
|
)
|
||||||
bookcase_selector.cmdloop()
|
bookcase_selector.cmdloop()
|
||||||
bookcase = bookcase_selector.result
|
bookcase = bookcase_selector.result
|
||||||
|
if bookcase == None:
|
||||||
|
return
|
||||||
|
|
||||||
bookcase_item.shelf = select_bookcase_shelf(bookcase, self.sql_session)
|
bookcase_item.shelf = select_bookcase_shelf(bookcase, self.sql_session)
|
||||||
|
|
||||||
@@ -152,6 +156,8 @@ class WorblehatCli(NumberedCmd):
|
|||||||
|
|
||||||
media_type_selector.cmdloop()
|
media_type_selector.cmdloop()
|
||||||
bookcase_item.media_type = media_type_selector.result
|
bookcase_item.media_type = media_type_selector.result
|
||||||
|
if bookcase_item.media_type == None:
|
||||||
|
return
|
||||||
|
|
||||||
username = input("Who owns this book? [PVV]> ")
|
username = input("Who owns this book? [PVV]> ")
|
||||||
if username != "":
|
if username != "":
|
||||||
|
|||||||
@@ -384,6 +384,8 @@ class EditBookcaseCli(NumberedCmd):
|
|||||||
)
|
)
|
||||||
bookcase_selector.cmdloop()
|
bookcase_selector.cmdloop()
|
||||||
bookcase = bookcase_selector.result
|
bookcase = bookcase_selector.result
|
||||||
|
if bookcase == None:
|
||||||
|
return
|
||||||
assert isinstance(bookcase, Bookcase)
|
assert isinstance(bookcase, Bookcase)
|
||||||
|
|
||||||
shelf = select_bookcase_shelf(bookcase, self.sql_session)
|
shelf = select_bookcase_shelf(bookcase, self.sql_session)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class Config:
|
|||||||
def read_password(password_field: str) -> str:
|
def read_password(password_field: str) -> str:
|
||||||
if Path(password_field).is_file():
|
if Path(password_field).is_file():
|
||||||
with Path(password_field).open() as f:
|
with Path(password_field).open() as f:
|
||||||
return f.read()
|
return f.read().strip()
|
||||||
else:
|
else:
|
||||||
return password_field
|
return password_field
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user