diff --git a/azos-core b/azos-core index 99c72c4..544f432 160000 --- a/azos-core +++ b/azos-core @@ -1 +1 @@ -Subproject commit 99c72c47186ac5cf74c9436fea8a22a21227da32 +Subproject commit 544f432cb6ac7ea7076213716ad886c87132c19d diff --git a/features/chess/default.nix b/features/chess/default.nix index 86761c4..813d9c0 100644 --- a/features/chess/default.nix +++ b/features/chess/default.nix @@ -4,13 +4,19 @@ in epkgs.trivialBuild { pname = "lichess"; - version = "0.8"; + version = "1.0"; src = pkgs.fetchFromGitHub { owner = "tmythicator"; repo = "lichess.el"; - rev = "1dd8a25ede7144c5d6be1f45f4ae3d07903783cd"; - sha256 = "157l4crbz37x367m69sxwvnd1pd8cqa6w0lcvyyvs27cm021d2gr"; + rev = "572a6a353e2113c8a95564b9bea1f2896e6d3dab"; + sha256 = "1d87qjmdpizggkrzq39i9vqgvbpjf5mv97vm7zy28ksbqxmfasqa"; }; + # trivialBuild's installPhase only installs *.el/*.elc; the piece SVGs + # under assets/ must be copied alongside so the default + # lichess-board-gui-asset-path (relative to the installed .el file) resolves. + postInstall = '' + cp -r assets $out/share/emacs/site-lisp/ + ''; }; config.flake.modules.homeManager.chess = { diff --git a/features/encryption/default.nix b/features/encryption/default.nix index e1fc501..855d021 100644 --- a/features/encryption/default.nix +++ b/features/encryption/default.nix @@ -39,6 +39,15 @@ home.file.".ssh/config".source = ./ssh-config; home.file.".ssh/gpg-as-ssh.pub".source = ./gpg-as-ssh.pub; home.file.".gnupg/sshcontrol".source = ./sshcontrol; + + # home-manager creates ~/.gnupg (via the files above) with the default + # umask, which can leave it group/other-readable. gpg refuses to trust + # a homedir like that and prints an "unsafe permissions" warning on + # every invocation, which pollutes anything that captures gpg/pass + # output (e.g. shell-command-to-string). Enforce 700 on every switch. + home.activation.gnupgPerms = lib.hm.dag.entryAfter ["writeBoundary"] '' + $DRY_RUN_CMD chmod 700 "$HOME/.gnupg" + ''; }; }; } diff --git a/features/lauretta/emacs/_pkg.nix b/features/lauretta/emacs/_pkg.nix index 3e50b04..1b9ecf2 100755 --- a/features/lauretta/emacs/_pkg.nix +++ b/features/lauretta/emacs/_pkg.nix @@ -15,6 +15,7 @@ orgTrivialBuild { pkgs.azos-emacs-station agent-shell + elfeed-protocol org-caldav pinentry ]; diff --git a/features/lauretta/emacs/config.org b/features/lauretta/emacs/config.org index 0648146..5508bf6 100644 --- a/features/lauretta/emacs/config.org +++ b/features/lauretta/emacs/config.org @@ -190,6 +190,94 @@ With prefix ARG, prompts to choose from all configured devices." (kbd "C") 'azos/caldav-sync) #+end_src +** Elfeed Nextcloud News Sync + +[[https://github.com/fasheng/elfeed-protocol][elfeed-protocol]] adds an =owncloud+= protocol that speaks the +ownCloud News API, which the Nextcloud News app also implements, so +it syncs elfeed's feed list and read/unread state with the Nextcloud +News app instead of just reading a local feed list one-way. + +Reuses the same =zakobar.com= pass entry as the CalDAV sync above, +since it's the same Nextcloud account. =shell-command-to-string= +merges stderr into its return value, so stderr is redirected away to +keep a stray gpg/pass warning from getting concatenated onto the +password. + +As of elfeed-protocol 1.0.0 (paired with elfeed >= 4.0.0), the +credentials go directly on =elfeed-feeds= — the older +=elfeed-protocol-feeds= variable is dead: setting it only logs a +deprecation warning, and =elfeed-feeds= ends up with the bare URL +and no =:password=, so requests silently authenticate with an empty +password and nothing ever lands in the db. + +#+begin_src emacs-lisp +(use-package elfeed-protocol + :after elfeed + :config + (setq elfeed-feeds + `(("owncloud+https://aner@nextcloud.zakobar.com" + :password ,(string-trim + (shell-command-to-string + "pass zakobar.com 2>/dev/null | head -1"))))) + (setq elfeed-protocol-enabled-protocols '(owncloud)) + (elfeed-protocol-enable)) +#+end_src + +** Elfeed Full Article Fetch + +Many feeds only publish a short excerpt. elfeed >= 4.0 has built-in +commands for this — =f= (=elfeed-show-fetch-link=) fetches the +linked page and appends it to the show buffer, =R= +(=elfeed-show-readable=) strips the fetched page down to +article text via eww's readability scorer — and both can run +automatically via =elfeed-show-update-hook=, gated on a feed's +=:fetch-link=/=:readable= metadata. + +That gating keys off an exact match on the feed's URL/id in +=elfeed-feeds=, which breaks for ownCloud/Nextcloud subfeeds: +elfeed-protocol synthesizes a per-subfeed id of the form +=::= that never appears in =elfeed-feeds= +(only the bare host URL does), so the metadata lookup always misses +and the stock hooks never fire. Replacing them with unconditional +versions makes full-text + readable-mode the default for every +entry instead. + +#+begin_src emacs-lisp +(defun azos/elfeed-show-auto-readable () + "Like `elfeed-show-auto-readable', but unconditional." + (unless (local-variable-p 'elfeed-transform-html-functions) + (let ((inhibit-message t)) + (elfeed-show-readable)))) + +(defun azos/elfeed-show-auto-fetch-link () + "Like `elfeed-show-auto-fetch-link', but unconditional." + (elfeed-show-fetch-link)) + +(setq elfeed-show-update-hook + (list #'azos/elfeed-show-auto-readable #'azos/elfeed-show-auto-fetch-link)) +#+end_src + +** Lichess + +=lichess.org= in pass already holds the website login password, and +lichess.el's =auth-source-pass= lookup resolves by bare hostname, so +the API token can't live under that same entry without colliding. +Store it separately under =lichess.org/token= (=pass insert +lichess.org/token=) and set the =lichess-token= variable directly — +=lichess-token= (the function) checks this variable before falling +back to =auth-source=, so this takes precedence without disturbing +the existing =lichess.org= entry or its consumers (e.g. browserpass). + +=shell-command-to-string= merges stderr into its return value, so any +gpg/pass warning on stderr (e.g. an unsafe-permissions notice) would +otherwise get concatenated onto the token and break auth silently. +Redirect stderr away so only the token itself is ever captured. + +#+begin_src emacs-lisp +(setq lichess-token + (string-trim (shell-command-to-string "pass lichess.org/token 2>/dev/null | head -1"))) +#+end_src + ** Beacon Remote Jobs #+begin_src emacs-lisp diff --git a/features/mail/default.nix b/features/mail/default.nix index ef003f7..6c1ddae 100644 --- a/features/mail/default.nix +++ b/features/mail/default.nix @@ -11,6 +11,7 @@ enable = true; create = "maildir"; }; + msmtp.enable = true; }; default_gmail_params = default_account_params @@ -20,6 +21,7 @@ default_smtp = { tls = { enable = true; + useStartTls = true; certificatesFile = "/etc/ssl/certs/ca-certificates.crt"; }; }; @@ -64,7 +66,6 @@ default_account_params // { address = "aner@zakobar.com"; - msmtp.enable = true; primary = true; userName = "aner@zakobar.com"; imap = {host = "mail.privateemail.com";}; diff --git a/nixos/configuration.nix b/nixos/configuration.nix index 2a8ef45..66d79b8 100644 --- a/nixos/configuration.nix +++ b/nixos/configuration.nix @@ -86,11 +86,9 @@ auto-optimise-store = true; substituters = [ "https://cache.nixos.org" - "https://cuda-maintainers.cachix.org" ]; trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" - "cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E=" ]; };