dotfiles/system/modules/scanservjs.nix

147 lines
4.1 KiB
Nix
Raw Permalink Normal View History

{ config
, lib
, pkgs
, ...}:
let
cfg = config.services.scanservjs;
2023-11-19 01:31:01 +07:00
settings = {
scanimage = "${pkgs.sane-backends}/bin/scanimage";
convert = "${pkgs.imagemagick}/bin/convert";
tesseract = "${pkgs.tesseract}/bin/tesseract";
} // cfg.settings;
2023-11-19 01:31:01 +07:00
settingsFormat = pkgs.formats.json { };
leafs = attrs:
builtins.concatLists
(lib.mapAttrsToList
2023-11-19 01:31:01 +07:00
(k: v: if builtins.isAttrs v then leafs v else [ v ])
attrs);
package = pkgs.scanservjs;
# config.host = '127.0.0.1';
# config.port = 8080;
# config.devices = [];
# config.ocrLanguage = 'eng';
# config.log.level = 'DEBUG';
# config.scanimage = '/usr/bin/scanimage';
# config.convert = '/usr/bin/convert';
# config.tesseract = '/usr/bin/tesseract';
# config.previewResolution = 100;
configFile = pkgs.writeText "config.local.js" ''
/* eslint-disable no-unused-vars */
module.exports = {
afterConfig(config) {
${builtins.concatStringsSep ""
(leafs
(lib.mapAttrsRecursive (path: val: ''
${builtins.concatStringsSep "." path} = ${builtins.toJSON val};
'') { config = settings; }))}
${cfg.extraConfig}
},
afterDevices(devices) {
${cfg.extraDevicesConfig}
},
async afterScan(fileInfo) {
${cfg.runAfterScan}
},
actions: [
2023-11-19 01:31:01 +07:00
${builtins.concatStringsSep ",\n" (map (x: "(${x})") cfg.extraActions)}
],
};
'';
in {
options.services.scanservjs = {
enable = lib.mkEnableOption (lib.mdDoc "scanservjs");
stateDir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/scanservjs";
description = lib.mdDoc ''
State directory for scanservjs
'';
};
settings = lib.mkOption {
2023-11-19 01:31:01 +07:00
default = { };
description = lib.mdDoc ''
Config to set in config.local.js's `afterConfig`
'';
type = lib.types.submodule {
freeformType = settingsFormat.type;
options.host = lib.mkOption {
type = lib.types.str;
description = "The IP to listen on";
default = "127.0.0.1";
};
options.port = lib.mkOption {
type = lib.types.port;
description = "The port to listen on";
default = 8080;
};
};
};
extraConfig = lib.mkOption {
default = "";
type = lib.types.lines;
description = lib.mdDoc ''
Extra code to add to config.local.js's `afterConfig`
'';
};
extraDevicesConfig = lib.mkOption {
default = "";
type = lib.types.lines;
description = lib.mdDoc ''
Extra code to add to config.local.js's `afterDevices`
'';
};
runAfterScan = lib.mkOption {
default = "";
type = lib.types.lines;
description = lib.mdDoc ''
Extra code to add to config.local.js's `afterScan`
'';
};
extraActions = lib.mkOption {
2023-11-19 01:31:01 +07:00
default = [ ];
type = lib.types.listOf lib.types.lines;
description = "Actions to add to config.local.js's `actions`";
};
};
2023-11-19 01:31:01 +07:00
config = lib.mkIf cfg.enable {
hardware.sane.enable = true;
users.users.scanservjs = {
group = "scanservjs";
extraGroups = [ "scanner" "lp" ];
home = cfg.stateDir;
isSystemUser = true;
2023-11-19 01:31:01 +07:00
createHome = lib.mkIf (cfg.stateDir != "/var/lib/scanservjs") true;
};
2023-11-19 01:31:01 +07:00
users.groups.scanservjs = { };
systemd.services.scanservjs = {
description = "scanservjs";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
# yes, those paths are configurable, but the config option isn't always used...
path = with pkgs; [ coreutils sane-backends imagemagick tesseract ];
environment.SANE_CONFIG_DIR = "/etc/sane-config";
environment.LD_LIBRARY_PATH = "/etc/sane-libs";
serviceConfig = {
2023-11-19 01:31:01 +07:00
ExecStart = "${package}/bin/scanservjs --config ${configFile}";
Restart = "always";
User = "scanservjs";
Group = "scanservjs";
2023-11-19 01:31:01 +07:00
StateDirectory = lib.mkIf (cfg.stateDir == "/var/lib/scanservjs") "scanservjs";
WorkingDirectory = cfg.stateDir;
};
};
};
}