#+title:    :app irc
#+subtitle: How neckbeards socialize
#+created:  June 11, 2017
#+since:    2.0.3

* Description :unfold:
This module turns Emacs into an IRC client, capable of OS notifications.

** Maintainers
/This module has no dedicated maintainers./ [[doom-contrib-maintainer:][Become a maintainer?]]

** Module flags
/This module has no flags./

** Packages
- [[doom-package:circe]]
- [[doom-package:circe-notifications]]

** Hacks
/No hacks documented for this module./

** TODO Changelog
# This section will be machine generated. Don't edit it by hand.
/This module does not have a changelog yet./

* Installation
[[id:01cffea4-3329-45e2-a892-95a384ab2338][Enable this module in your ~doom!~ block.]]

This module requires:
- [[https://www.gnutls.org/][GnuTLS]], for secure IRC connections to work.

This should be available through your OS package manager.

** macOS
#+begin_src sh
brew install gnutls
#+end_src

** Debian / Ubuntu
#+begin_src sh
apt install gnutls-bin
#+end_src

** Arch Linux
#+begin_src sh
pacman -S gnutls
#+end_src
** NixOS
#+begin_src nix
environment.systemPackages = [ pkgs.gnutls ];
#+end_src

* TODO Usage
#+begin_quote
 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote

To connect to IRC use ~M-x =irc~.

When in a circe buffer these keybindings will be available:
| command                     | key             | description                                  |
|-----------------------------+-----------------+----------------------------------------------|
| ~+irc/tracking-next-buffer~ | [[kbd:][<localleader> a]] | Switch to the next active buffer             |
| ~circe-command-JOIN~        | [[kbd:][<localleader> j]] | Join a channel                               |
| ~+irc/send-message~         | [[kbd:][<localleader> m]] | Send a private message                       |
| ~circe-command-NAMES~       | [[kbd:][<localleader> n]] | List the names of the current channel        |
| ~circe-command-PART~        | [[kbd:][<localleader> p]] | Part the current channel                     |
| ~+irc/quit~                 | [[kbd:][<localleader> Q]] | Kill the current circe session and workgroup |
| ~circe-reconnect~           | [[kbd:][<localleader> R]] | Reconnect the current server                 |

* TODO Configuration
#+begin_quote
 󱌣 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote

Use ~set-irc-server! SERVER PLIST~ to configure IRC servers. Its second argument
(a plist) takes the same arguments as ~circe-network-options~:
#+begin_src emacs-lisp
;; if you omit =:host=, ~SERVER~ will be used instead.
(after! circe
  (set-irc-server! "irc.libera.chat"
    `(:tls t
      :port 6697
      :nick "doom"
      :sasl-username "myusername"
      :sasl-password "mypassword"
      :channels ("#emacs"))))
#+end_src

However, *it is a obviously a bad idea to store your password in plaintext,* so
here are ways to avoid that:

** TODO Pass: the unix password manager
#+begin_quote
 󱌣 /This section is outdated and needs to be rewritten./ [[doom-contrib-module:][Rewrite it?]]
#+end_quote

[[https://www.passwordstore.org/][Pass]] is my tool of choice. I use it to manage my passwords. If you activate the
[[doom-module::tools pass]] module you get an elisp API through which to access your password
store.

~set-irc-server!~ accepts a plist can use functions instead of strings.
~+pass-get-user~ and ~+pass-get-secret~ can help here:
#+begin_src emacs-lisp
(set-irc-server! "irc.libera.chat"
  `(:tls t
    :port 6697
    :nick "doom"
    :sasl-username ,(+pass-get-user   "irc/libera.chat")
    :sasl-password ,(+pass-get-secret "irc/libera.chat")
    :channels ("#emacs")))
#+end_src

But wait, there's more! This stores your password in a public variable which
could be accessed or appear in backtraces. Not good! So we go a step further:
#+begin_src emacs-lisp
(set-irc-server! "irc.libera.chat"
  `(:tls t
    :port 6697
    :nick "doom"
    :sasl-username ,(+pass-get-user "irc/libera.chat")
    :sasl-password (lambda (&rest _) (+pass-get-secret "irc/libera.chat"))
    :channels ("#emacs")))
#+end_src

And you're good to go!

Note that ~+pass-get-user~ tries to find your username by looking for the fields
listed in ~+pass-user-fields~ (by default =login=, =user==, =username== and
=email=)=). An example configuration looks like

#+begin_example
mysecretpassword
username: myusername
#+end_example

** Emacs' auth-source API
~auth-source~ is built into Emacs. As suggested [[https://github.com/jorgenschaefer/circe/wiki/Configuration#safer-password-management][in the circe wiki]], you can store
(and retrieve) encrypted passwords with it.
#+begin_src emacs-lisp
(setq auth-sources '("~/.authinfo.gpg"))

(defun my-fetch-password (&rest params)
  (require 'auth-source)
  (let ((match (car (apply #'auth-source-search params))))
    (if match
        (let ((secret (plist-get match :secret)))
          (if (functionp secret)
              (funcall secret)
            secret))
      (error "Password not found for %S" params))))

(defun my-nickserv-password (server)
  (my-fetch-password :user "forcer" :host "irc.libera.chat"))

(set-irc-server! "irc.libera.chat"
  '(:tls t
    :port 6697
    :nick "doom"
    :sasl-password my-nickserver-password
    :channels ("#emacs")))
#+end_src

* TODO Troubleshooting
/There are no known problems with this module./ [[doom-report:][Report one?]]

* Frequently asked questions
/This module has no FAQs yet./ [[doom-suggest-faq:][Ask one?]]

* TODO Appendix
#+begin_quote
 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote
