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
|
{ depot, pkgs, lib, ... }:
# mastodon-alt-text — alt text for the clipboard image, with a choice of
# wordings.
#
# The binary is both the launcher and the server: bare invocation restarts the
# systemd user unit and opens a browser at it, `serve` is what the unit runs.
#
# xclip and imagemagick are pinned because they are load-bearing implementation
# details. The browser is *not* pinned: it is looked up on PATH (and overridable
# with -browser), so this uses the chromium the machine already has rather than
# dragging a second one into the closure.
let
unwrapped = depot.nix.buildGo.program {
name = "mastodon-alt-text";
srcs = [
./main.go
./serve.go
./gemini.go
./clipboard.go
./templates.go
];
};
in
pkgs.symlinkJoin {
name = "mastodon-alt-text";
outputs = [ "out" "man" ];
paths = [ unwrapped ];
buildInputs = [ pkgs.makeWrapper ];
postBuild = ''
# xclip reads the image and owns the resulting selections; magick does the
# PNG→WebP conversion that keeps the upload small. pass(1) is intentionally
# left to PATH, since it needs the user's own store and agent.
wrapProgram $out/bin/mastodon-alt-text \
--prefix PATH : ${lib.makeBinPath [ pkgs.xclip pkgs.imagemagick ]}
mkdir -p $man/share/man/man1
cp ${./mastodon-alt-text.1} $man/share/man/man1/mastodon-alt-text.1
'';
meta = {
description = "Generate Mastodon alt text for the image in the clipboard";
longDescription = ''
Reads an image from the X11 CLIPBOARD selection, converts it to WebP and
asks Gemini 2.5 Flash for three alt texts, generated concurrently at a
raised temperature so the wordings actually differ. The results stream
into a browser window as they arrive; clicking one copies it to both the
PRIMARY and CLIPBOARD selections.
The server runs as a systemd user unit and stops on its own once the
window has been closed for a minute. Its idle timeout is monotonic, so
suspending the machine does not cause it to disappear mid-sleep.
The API key comes from $GEMINI_API_KEY or pass(1).
'';
mainProgram = "mastodon-alt-text";
};
}
|