~ruther/guix-local

2f204a73036d3f78bb3a8a99833ac69a9efaab7b — Janneke Nieuwenhuizen 1 year, 3 months ago 973e59e
services: Add snuik-service-type.

* gnu/services/messaging.scm (snuik-configuration): New type.
(snuik-services): New procedure.
(snuik-activation, %snuik-accounts, snuik-service-type): New variables.
* doc/guix.texi (Messaging Services): Document it.

Change-Id: I0c52b4804948876dc1b4d3b5ac660af848a13f25
2 files changed, 171 insertions(+), 2 deletions(-)

M doc/guix.texi
M gnu/services/messaging.scm
M doc/guix.texi => doc/guix.texi +58 -1
@@ 36,7 36,7 @@ Copyright @copyright{} 2016, 2017, 2018, 2021 Chris Marusich@*
Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Efraim Flashner@*
Copyright @copyright{} 2016 John Darrington@*
Copyright @copyright{} 2016, 2017 Nikita Gillmann@*
Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Janneke Nieuwenhuizen@*
Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025 Janneke Nieuwenhuizen@*
Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021 Julien Lepiller@*
Copyright @copyright{} 2016 Alex ter Weele@*
Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021 Christopher Baines@*


@@ 30218,6 30218,63 @@ and Error.
@end table
@end deftp

@cindex irc-bot
@cindex snuik
The @uref{https://gitlab.com/janneke/snuik, Snuik IRC bot} can be run as
a daemon to aid talking to users that are currently offline.  With the
@code{(gnu services messaging)} service, you can configure it by adding
a @code{snuik-service-type} service to the @code{services} field of your
operating system declaration.

@defvar snuik-service-type
This is the type of the Snuik service, whose value is a
@code{snuik-configuration} object.
@end defvar

Here is an example of a service and its configuration:

@lisp
(service snuik-service-type
         (snuik-configuration
          (password-file "/var/run/snuik/.password.snuik")
          (channels '("#bootstrappable"
                      "#dezyne"
                      "#guix-risc-v"
                      "#lilypond"))))
@end lisp

@deftp {Data Type} snuik-configuration
Available @code{snuik-configuration} fields are:

@table @asis
@item @code{snuik} (default: @code{snuik}) (type: package)
The Snuik package to use.

@item @code{server} (default: @code{"irc.libera.chat"})
The IRC server to connect to.

@item @code{port} (default: @code{6665}) (type: integer)
Port number used by the IRC server.

@item @code{nick} (default: @code{"snuik"}) (type: string)
The nickname for snuik to use.

@item @code{password} (default: @code{#f}) (type: string)
The password to use when logging in.

@item @code{password-file} (default: @code{".password.<nick>})
The file to read the password from to use when logging in.

@item @code{channels} (default: @code{'("##botchat")})
The channels for snuik to join, a list of strings.

@item @code{extra-options} (default: @code{'()})
Extra options will be passed to @command{snuik}, please run
@command{snuik --help } for more information.

@end table
@end deftp

@node Telephony Services
@subsection Telephony Services


M gnu/services/messaging.scm => gnu/services/messaging.scm +113 -1
@@ 59,7 59,10 @@
            bitlbee-service-type

            quassel-configuration
            quassel-service-type))
            quassel-service-type

            snuik-configuration
            snuik-service-type))

;;; Commentary:
;;;


@@ 1002,3 1005,112 @@ a gateway between IRC and chat networks.")))
                 "Run @url{https://quassel-irc.org/,quasselcore}, the backend
for the distributed IRC client quassel, which allows you to connect from
multiple machines simultaneously.")))


;;;
;;; Snuik.
;;;
(define-maybe integer (no-serialization))
(define-configuration/no-serialization snuik-configuration
  (snuik         (package snuik)       "The snuik package to use.")
  (server        maybe-string          "The IRC server to connect to.")
  (port          maybe-integer         "The port used by the IRC server.")
  (nick          maybe-string          "The nickname for snuik to use.")
  (password      maybe-string          "The password to use when logging in.")
  (password-file maybe-string          "The file to read the password from.")
  (channels      (list-of-strings '()) "The channels for snuik to join.")
  (extra-options (list-of-strings '()) "Extra options to be passed to snuik.")
  (home-service? (boolean for-home?)   "Running as home service?"))

(define (snuik-services config)
  "Return a <shepherd-service> for snuik with CONFIG."
  (match-record config
      <snuik-configuration>
      (snuik server port nick password password-file channels extra-options
             home-service?)
    (let* ((password-file (snuik-configuration-password-file config))
           (mappings `(,@(if home-service?
                             '()
                             `(,(file-system-mapping
                                 (source "/var/run/snuik")
                                 (target source)
                                 (writable? #t))
                               ,@(if password-file
                                     (list (file-system-mapping
                                            (source password-file)
                                            (target source)))
                                     '())))))
           (snuik (least-authority-wrapper
                   (file-append snuik "/bin/snuik")
                   #:name "snuik"
                   #:mappings mappings
                   #:namespaces (delq 'net %namespaces)))
           (command
            #~'(#$snuik
                #$@(if (and server (not (eq? server %unset-value)))
                       (list (string-append "--server=" server))
                       #~())
                #$@(if (and port (not (eq? port %unset-value)))
                       (list (string-append "--port=" (number->string port)))
                       #~())
                #$@(if (and nick (not (eq? nick %unset-value)))
                       (list (string-append "--nick=" nick))
                       #~())
                #$@(if (and password (not (eq? password %unset-value)))
                       (list (string-append "--password=" password))
                       #~())
                #$@(if (and password-file (not (eq? password-file %unset-value)))
                       (list (string-append "--password-file=" password-file))
                       #~())
                #$@(if (pair? channels)
                       (list (string-append "--channels=" (string-join channels ",")))
                       #~())
                #$@extra-options))
           (log-file #~(string-append
                        #$(if home-service? #~%user-log-dir "/var/log")
                        "/snuik.log")))
      (list (shepherd-service
             (documentation "Run the snuik IRC bot.")
             (provision '(snuik))
             (requirement (if home-service? '() '(user-processes networking)))
             (modules (if home-service?
                          '((shepherd support)) ;for '%user-log-dir'
                          '()))
             (start #~(make-forkexec-constructor
                       #$command
                       #:log-file #$log-file
                       #:user #$(and (not home-service?) "snuik")
                       #:group #$(and (not home-service?) "snuik")))
             (stop #~(make-kill-destructor)))))))

(define snuik-activation
  (with-imported-modules '((guix build utils))
    #~(begin
        (use-modules (guix build utils))
        (let* ((user (getpw "snuik"))
               (directory "/var/run/snuik"))
          (mkdir-p directory)
          (chown directory (passwd:uid user) (passwd:gid user))))))

(define %snuik-accounts
  (list (user-group (name "snuik") (system? #t))
        (user-account
         (name "snuik")
         (group "snuik")
         (system? #t)
         (comment "Snuik IRC bot user")
         (home-directory "/var/run/snuik")
         (shell (file-append shadow "/sbin/nologin")))))

(define snuik-service-type
  (service-type
   (name 'home-snuik)
   (description "Run the Snuik IRC bot.")
   (default-value (snuik-configuration))
   (extensions
    (list (service-extension activation-service-type
                             (const snuik-activation))
          (service-extension account-service-type
                             (const %snuik-accounts))
          (service-extension shepherd-root-service-type
                             snuik-services)))))