Commit Graph
5 Commits
Author SHA1 Message Date
JakeBreath b3ceac52ed fish greeting: win over distro configs that define fish_greeting inline
On CachyOS (and OMF-style setups) config.fish sources a distro file that
defines fish_greeting while the shell starts. A function defined that way
beats autoloading from functions/, so the installed greeting never ran.

install.fish now appends a guarded block to ~/.config/fish/config.fish that
sources the greeting after everything else (idempotent via a marker, skipped
with --no-config), and the README documents the symptom, the check
(functions --details fish_greeting) and the manual one-liner.

Verified in a sandbox HOME that reproduces the CachyOS setup: before the
install fish resolves the distro file and prints its message, after it
resolves ~/.config/fish/functions/fish_greeting.fish and runs ours; a second
install leaves a single block. Applied to this machine's real config as
well, where fish_greeting now resolves to the user function and the
__j621_fetch_random helper is loaded.
2026-09-18 13:48:02 -05:00
JakeBreath bcff184a64 Make extras/fish_greeting/install.fish executable
It has a '#!/usr/bin/env fish' shebang but was committed as mode 644, so
./install.fish answered 'Permission denied' on a fresh clone. Mode is now
100755 like the deploy scripts; 'fish install.fish' worked either way.
2026-09-18 13:43:12 -05:00
JakeBreath 770b1e5ee6 Scoped API tokens for the random endpoint, with a management page
Backend: a GreetingToken model stores only a SHA-256 hash of a j621r_…
key (shown once at creation) plus label, prefix, created/last-used. A
dedicated GreetingTokenAuthentication understands the usual
'Authorization: Token …' header but is registered only on RandomItemView
(alongside the normal token auth), so a greeting token authenticates
/api/random/ and is rejected with 401 everywhere else — exactly the scope
shell greetings need. Endpoints: GET/POST /api/auth/greeting-tokens/ and
DELETE /api/auth/greeting-tokens/{id}/ (own tokens only; the list never
returns keys or hashes).

Frontend: /tokens page (Account → Shell tokens card, command palette entry)
lists tokens with label, prefix, created/last-used and revoke (shared
confirm dialog). Creating one shows the key with Copy and 'Copy for fish'
buttons plus a pointer to extras/fish_greeting.

Tests: apps/accounts/tests/test_greeting_tokens.py — 9 tests covering
create-once semantics and hashing, hidden keys in listings, the scope
guarantee (random 200 with a signed URL; 401 on files, storage, me, tags
cloud, delete and the token list itself), unknown/revoked keys, cross-user
revocation, last-used tracking and label limits.

Verified live: created a token, rolled /random (signed URL), got 401 from
four other endpoints, saw the list omit secrets, revoked it (204) and the
same key then 401'd on /random. Full suite: 39 tests green.
2026-09-18 13:37:29 -05:00
JakeBreath 2d9493d9fe fish_greeting installer asks for the API origin and probes the backend
install.fish now:
- asks for the API origin (default https://j621.rainbow-herring.ts.net) and
  an optional token when run interactively, or takes --url/--token;
- writes ~/.config/j621Greeting/config.fish with mode 600 (it may hold a
  token), keeps an existing config unless --force/--url is given, and
  --no-prompt runs fully unattended;
- verifies the setup: /health must answer 'ok' and a fastfetch random roll is
  attempted, reporting the API's own message when it finds nothing; exits
  non-zero when the backend is unreachable so scripts notice.

README documents the prompts/flags, the chmod 600 config, and that the
greeting is designed to run without a token (guest mode: unsigned links,
guest-visible items only) with a token adding signed links and hidden items.

Tested with fish 4.9.3 in throwaway HOME dirs: flag-driven install with a
token, interactive install with a piped origin and no token, re-run keeping
the existing config, and an unreachable backend exiting 1.
2026-09-18 13:22:55 -05:00
JakeBreath aee29de34a Port the fish_greeting shell greeting to the new API
The original script (J621-Django/extras/fish_greeting system) downloaded
image bytes from /random/?rating=X and read the X-File-* headers. The new
API answers with JSON and a signed link, so the greeting now:

- asks /api/random/?fastfetch=1&rating=<mode> for JSON;
- parses url/j_id/filename/md5 with jq, python3, or a grep/sed fallback;
- downloads the signed link and keeps the original display path (fastfetch
  kitty/kitty-icat logos, gifsicle preprocessing for GIFs, recursion guard,
  logging with rotation, greeting_mode 0/1/2 = NSFW/SFW/Questionable);
- is configured through ~/.config/j621Greeting/config.fish or universal
  variables (J621_BASE, J621_WEB, J621_TOKEN, J621_FASTFETCH_CONFIG) instead
  of a hardcoded host, and prints the /detail/<J-ID> link on J621_WEB;
- reports the API's own 404 message when a rating has no images, and keeps
  curl quiet so failures do not spill into the greeting.

extras/fish_greeting/ contains the function, an install.fish (copies it into
the fish functions dir, creates the config once, checks dependencies) and a
README with the old-vs-new table and troubleshooting. The existing
gm-switch helper and .desktop launchers keep working (same mode file).

Tested with fish 4.9.3: syntax check on every file, guest and token runs
against the dev API (unsigned vs signed URLs), the empty-rating and
unreachable-API paths, and the grep/sed fallback with jq and python3
unavailable.
2026-09-18 13:14:41 -05:00