// The cups module's tools (novox/hq research 027/02, 026/05): the printers, their state, supplies and // driver, the queue, and printing, cancelling and choosing the default. A Go bundle the node's runtime // launches over stdio (ADR 0188, ADR 0193); it runs as the operator account. An act CUPS keeps for // its administrators goes through `sudo -n`. package main import ( "fmt" "os" stdio "git.novox.be/novox/mesh-sdk/go" ) var providedBy = map[string]string{ "lpstat": "the cups package, which this module installs", "lpoptions": "the cups package, which this module installs", "lp": "the cups package, which this module installs", "cancel": "the cups package, which this module installs", "lpadmin": "the cups package, which this module installs", "lpinfo": "the cups package, which this module installs", "cupsenable": "the cups package, which this module installs", "cupsaccept": "the cups package, which this module installs", "pacman": "this is not an Arch machine", } func main() { if err := stdio.Serve("", tools()); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } var printerArg = map[string]any{"type": "string", "description": "the printer's queue name, as cups_printers answers it"} func tools() []stdio.Tool { return []stdio.Tool{ { Name: "cups_printers", Description: "Every printer queue: state, whether it is enabled and accepting jobs, the default, its device " + "address, make and model, whether it prints driverless (IPP Everywhere), the reasons for its state, and " + "supply levels where the printer reports them. (r)", Input: map[string]any{}, Run: func(map[string]any) (any, error) { return Printers() }, }, { Name: "cups_queue", Description: "The jobs waiting or printing, on every printer or one; or, with completed, the finished ones. " + "Each with its id, printer, owner, size and when it was submitted. (r)", Input: map[string]any{ "printer": printerArg, "completed": map[string]any{"type": "boolean", "description": "the finished jobs instead"}, "limit": map[string]any{"type": "integer", "description": "at most this many, newest first (default 50, at most 500)"}, }, Run: func(args map[string]any) (any, error) { p, err := optText(args, "printer", "") if err != nil { return nil, err } done, err := optFlag(args, "completed", false) if err != nil { return nil, err } limit, err := optWhole(args, "limit", 50, 1, 500) if err != nil { return nil, err } return Queue(p, done, limit) }, }, { Name: "cups_cancel", Description: "Cancel one job by its id (\"Brother-12\" or 12), or every job on a printer with all. Another " + "account's job is cancelled through sudo -n. (a)", Input: map[string]any{ "job": map[string]any{"type": "string", "description": "the job id"}, "printer": printerArg, "all": map[string]any{"type": "boolean", "description": "every job on printer"}, }, Run: func(args map[string]any) (any, error) { job, err := optText(args, "job", "") if err != nil { return nil, err } p, err := optText(args, "printer", "") if err != nil { return nil, err } all, err := optFlag(args, "all", false) if err != nil { return nil, err } return Cancel(job, p, all) }, }, { Name: "cups_print", Description: "Print a file on this machine, to a printer or the default, with copies and IPP options such as " + "sides=two-sided-long-edge or media=A4. Answers the job id. (a)", Input: map[string]any{ "file": map[string]any{"type": "string", "description": "the file's absolute path on this machine"}, "printer": printerArg, "copies": map[string]any{"type": "integer", "description": "copies (default 1, at most 99)"}, "options": map[string]any{"type": "object", "additionalProperties": map[string]any{"type": "string"}, "description": "IPP options, name to value"}, "title": map[string]any{"type": "string", "description": "the job's title (default the file's name)"}, }, Run: func(args map[string]any) (any, error) { file, err := text(args, "file") if err != nil { return nil, err } p, err := optText(args, "printer", "") if err != nil { return nil, err } copies, err := optWhole(args, "copies", 1, 1, 99) if err != nil { return nil, err } opts, err := optionsOf(args) if err != nil { return nil, err } title, err := optText(args, "title", "") if err != nil { return nil, err } return Print(file, p, copies, opts, title) }, }, { Name: "cups_default", Description: "The machine's default printer; with printer, make that printer the default (through sudo -n). " + "The default is CUPS's own setting, kept as the operator chose it: the mesh does not declare it. (r/a)", Input: map[string]any{"printer": printerArg}, Run: func(args map[string]any) (any, error) { p, err := optText(args, "printer", "") if err != nil { return nil, err } return Default(p) }, }, { Name: "cups_resume", Description: "Enable a printer and make it accept jobs again, after CUPS stopped it on an error. Through sudo -n. (a)", Input: map[string]any{"printer": printerArg}, Run: func(args map[string]any) (any, error) { p, err := text(args, "printer") if err != nil { return nil, err } return Resume(p) }, }, { Name: "cups_drivers", Description: "What each printer prints through (driverless or a driver's PPD), the packages that bring drivers " + "and backends, which of them are from outside the official repositories, and the driver models CUPS " + "offers, filtered by match. (r)", Input: map[string]any{ "match": map[string]any{"type": "string", "description": "only models whose description contains this, any case"}, "limit": map[string]any{"type": "integer", "description": "at most this many models (default 50, at most 1000)"}, }, Run: func(args map[string]any) (any, error) { match, err := optText(args, "match", "") if err != nil { return nil, err } limit, err := optWhole(args, "limit", 50, 0, 1000) if err != nil { return nil, err } return Drivers(match, limit) }, }, } }